mirror of
https://github.com/HDT3213/godis.git
synced 2025-10-05 00:42:43 +08:00
rename godis/redis/reply to godis/redis/protocol
This commit is contained in:
12
aof/aof.go
12
aof/aof.go
@@ -7,7 +7,7 @@ import (
|
|||||||
"github.com/hdt3213/godis/lib/utils"
|
"github.com/hdt3213/godis/lib/utils"
|
||||||
"github.com/hdt3213/godis/redis/connection"
|
"github.com/hdt3213/godis/redis/connection"
|
||||||
"github.com/hdt3213/godis/redis/parser"
|
"github.com/hdt3213/godis/redis/parser"
|
||||||
"github.com/hdt3213/godis/redis/reply"
|
"github.com/hdt3213/godis/redis/protocol"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
"strconv"
|
||||||
@@ -78,7 +78,7 @@ func (handler *Handler) handleAof() {
|
|||||||
handler.pausingAof.RLock() // prevent other goroutines from pausing aof
|
handler.pausingAof.RLock() // prevent other goroutines from pausing aof
|
||||||
if p.dbIndex != handler.currentDB {
|
if p.dbIndex != handler.currentDB {
|
||||||
// select db
|
// select db
|
||||||
data := reply.MakeMultiBulkReply(utils.ToCmdLine("SELECT", strconv.Itoa(p.dbIndex))).ToBytes()
|
data := protocol.MakeMultiBulkReply(utils.ToCmdLine("SELECT", strconv.Itoa(p.dbIndex))).ToBytes()
|
||||||
_, err := handler.aofFile.Write(data)
|
_, err := handler.aofFile.Write(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warn(err)
|
logger.Warn(err)
|
||||||
@@ -86,7 +86,7 @@ func (handler *Handler) handleAof() {
|
|||||||
}
|
}
|
||||||
handler.currentDB = p.dbIndex
|
handler.currentDB = p.dbIndex
|
||||||
}
|
}
|
||||||
data := reply.MakeMultiBulkReply(p.cmdLine).ToBytes()
|
data := protocol.MakeMultiBulkReply(p.cmdLine).ToBytes()
|
||||||
_, err := handler.aofFile.Write(data)
|
_, err := handler.aofFile.Write(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Warn(err)
|
logger.Warn(err)
|
||||||
@@ -135,13 +135,13 @@ func (handler *Handler) LoadAof(maxBytes int) {
|
|||||||
logger.Error("empty payload")
|
logger.Error("empty payload")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
r, ok := p.Data.(*reply.MultiBulkReply)
|
r, ok := p.Data.(*protocol.MultiBulkReply)
|
||||||
if !ok {
|
if !ok {
|
||||||
logger.Error("require multi bulk reply")
|
logger.Error("require multi bulk protocol")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
ret := handler.db.Exec(fakeConn, r.Args)
|
ret := handler.db.Exec(fakeConn, r.Args)
|
||||||
if reply.IsErrorReply(ret) {
|
if protocol.IsErrorReply(ret) {
|
||||||
logger.Error("exec err", err)
|
logger.Error("exec err", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -6,17 +6,17 @@ import (
|
|||||||
"github.com/hdt3213/godis/datastruct/set"
|
"github.com/hdt3213/godis/datastruct/set"
|
||||||
SortedSet "github.com/hdt3213/godis/datastruct/sortedset"
|
SortedSet "github.com/hdt3213/godis/datastruct/sortedset"
|
||||||
"github.com/hdt3213/godis/interface/database"
|
"github.com/hdt3213/godis/interface/database"
|
||||||
"github.com/hdt3213/godis/redis/reply"
|
"github.com/hdt3213/godis/redis/protocol"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
// EntityToCmd serialize data entity to redis command
|
// EntityToCmd serialize data entity to redis command
|
||||||
func EntityToCmd(key string, entity *database.DataEntity) *reply.MultiBulkReply {
|
func EntityToCmd(key string, entity *database.DataEntity) *protocol.MultiBulkReply {
|
||||||
if entity == nil {
|
if entity == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
var cmd *reply.MultiBulkReply
|
var cmd *protocol.MultiBulkReply
|
||||||
switch val := entity.Data.(type) {
|
switch val := entity.Data.(type) {
|
||||||
case []byte:
|
case []byte:
|
||||||
cmd = stringToCmd(key, val)
|
cmd = stringToCmd(key, val)
|
||||||
@@ -34,17 +34,17 @@ func EntityToCmd(key string, entity *database.DataEntity) *reply.MultiBulkReply
|
|||||||
|
|
||||||
var setCmd = []byte("SET")
|
var setCmd = []byte("SET")
|
||||||
|
|
||||||
func stringToCmd(key string, bytes []byte) *reply.MultiBulkReply {
|
func stringToCmd(key string, bytes []byte) *protocol.MultiBulkReply {
|
||||||
args := make([][]byte, 3)
|
args := make([][]byte, 3)
|
||||||
args[0] = setCmd
|
args[0] = setCmd
|
||||||
args[1] = []byte(key)
|
args[1] = []byte(key)
|
||||||
args[2] = bytes
|
args[2] = bytes
|
||||||
return reply.MakeMultiBulkReply(args)
|
return protocol.MakeMultiBulkReply(args)
|
||||||
}
|
}
|
||||||
|
|
||||||
var rPushAllCmd = []byte("RPUSH")
|
var rPushAllCmd = []byte("RPUSH")
|
||||||
|
|
||||||
func listToCmd(key string, list *List.LinkedList) *reply.MultiBulkReply {
|
func listToCmd(key string, list *List.LinkedList) *protocol.MultiBulkReply {
|
||||||
args := make([][]byte, 2+list.Len())
|
args := make([][]byte, 2+list.Len())
|
||||||
args[0] = rPushAllCmd
|
args[0] = rPushAllCmd
|
||||||
args[1] = []byte(key)
|
args[1] = []byte(key)
|
||||||
@@ -53,12 +53,12 @@ func listToCmd(key string, list *List.LinkedList) *reply.MultiBulkReply {
|
|||||||
args[2+i] = bytes
|
args[2+i] = bytes
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
return reply.MakeMultiBulkReply(args)
|
return protocol.MakeMultiBulkReply(args)
|
||||||
}
|
}
|
||||||
|
|
||||||
var sAddCmd = []byte("SADD")
|
var sAddCmd = []byte("SADD")
|
||||||
|
|
||||||
func setToCmd(key string, set *set.Set) *reply.MultiBulkReply {
|
func setToCmd(key string, set *set.Set) *protocol.MultiBulkReply {
|
||||||
args := make([][]byte, 2+set.Len())
|
args := make([][]byte, 2+set.Len())
|
||||||
args[0] = sAddCmd
|
args[0] = sAddCmd
|
||||||
args[1] = []byte(key)
|
args[1] = []byte(key)
|
||||||
@@ -68,12 +68,12 @@ func setToCmd(key string, set *set.Set) *reply.MultiBulkReply {
|
|||||||
i++
|
i++
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
return reply.MakeMultiBulkReply(args)
|
return protocol.MakeMultiBulkReply(args)
|
||||||
}
|
}
|
||||||
|
|
||||||
var hMSetCmd = []byte("HMSET")
|
var hMSetCmd = []byte("HMSET")
|
||||||
|
|
||||||
func hashToCmd(key string, hash dict.Dict) *reply.MultiBulkReply {
|
func hashToCmd(key string, hash dict.Dict) *protocol.MultiBulkReply {
|
||||||
args := make([][]byte, 2+hash.Len()*2)
|
args := make([][]byte, 2+hash.Len()*2)
|
||||||
args[0] = hMSetCmd
|
args[0] = hMSetCmd
|
||||||
args[1] = []byte(key)
|
args[1] = []byte(key)
|
||||||
@@ -85,12 +85,12 @@ func hashToCmd(key string, hash dict.Dict) *reply.MultiBulkReply {
|
|||||||
i++
|
i++
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
return reply.MakeMultiBulkReply(args)
|
return protocol.MakeMultiBulkReply(args)
|
||||||
}
|
}
|
||||||
|
|
||||||
var zAddCmd = []byte("ZADD")
|
var zAddCmd = []byte("ZADD")
|
||||||
|
|
||||||
func zSetToCmd(key string, zset *SortedSet.SortedSet) *reply.MultiBulkReply {
|
func zSetToCmd(key string, zset *SortedSet.SortedSet) *protocol.MultiBulkReply {
|
||||||
args := make([][]byte, 2+zset.Len()*2)
|
args := make([][]byte, 2+zset.Len()*2)
|
||||||
args[0] = zAddCmd
|
args[0] = zAddCmd
|
||||||
args[1] = []byte(key)
|
args[1] = []byte(key)
|
||||||
@@ -102,16 +102,16 @@ func zSetToCmd(key string, zset *SortedSet.SortedSet) *reply.MultiBulkReply {
|
|||||||
i++
|
i++
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
return reply.MakeMultiBulkReply(args)
|
return protocol.MakeMultiBulkReply(args)
|
||||||
}
|
}
|
||||||
|
|
||||||
var pExpireAtBytes = []byte("PEXPIREAT")
|
var pExpireAtBytes = []byte("PEXPIREAT")
|
||||||
|
|
||||||
// MakeExpireCmd generates command line to set expiration for the given key
|
// MakeExpireCmd generates command line to set expiration for the given key
|
||||||
func MakeExpireCmd(key string, expireAt time.Time) *reply.MultiBulkReply {
|
func MakeExpireCmd(key string, expireAt time.Time) *protocol.MultiBulkReply {
|
||||||
args := make([][]byte, 3)
|
args := make([][]byte, 3)
|
||||||
args[0] = pExpireAtBytes
|
args[0] = pExpireAtBytes
|
||||||
args[1] = []byte(key)
|
args[1] = []byte(key)
|
||||||
args[2] = []byte(strconv.FormatInt(expireAt.UnixNano()/1e6, 10))
|
args[2] = []byte(strconv.FormatInt(expireAt.UnixNano()/1e6, 10))
|
||||||
return reply.MakeMultiBulkReply(args)
|
return protocol.MakeMultiBulkReply(args)
|
||||||
}
|
}
|
||||||
|
@@ -5,7 +5,7 @@ import (
|
|||||||
"github.com/hdt3213/godis/interface/database"
|
"github.com/hdt3213/godis/interface/database"
|
||||||
"github.com/hdt3213/godis/lib/logger"
|
"github.com/hdt3213/godis/lib/logger"
|
||||||
"github.com/hdt3213/godis/lib/utils"
|
"github.com/hdt3213/godis/lib/utils"
|
||||||
"github.com/hdt3213/godis/redis/reply"
|
"github.com/hdt3213/godis/redis/protocol"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
@@ -55,7 +55,7 @@ func (handler *Handler) DoRewrite(ctx *RewriteCtx) error {
|
|||||||
// rewrite aof tmpFile
|
// rewrite aof tmpFile
|
||||||
for i := 0; i < config.Properties.Databases; i++ {
|
for i := 0; i < config.Properties.Databases; i++ {
|
||||||
// select db
|
// select db
|
||||||
data := reply.MakeMultiBulkReply(utils.ToCmdLine("SELECT", strconv.Itoa(i))).ToBytes()
|
data := protocol.MakeMultiBulkReply(utils.ToCmdLine("SELECT", strconv.Itoa(i))).ToBytes()
|
||||||
_, err := tmpFile.Write(data)
|
_, err := tmpFile.Write(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -128,7 +128,7 @@ func (handler *Handler) FinishRewrite(ctx *RewriteCtx) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// sync tmpFile's db index with online aofFile
|
// sync tmpFile's db index with online aofFile
|
||||||
data := reply.MakeMultiBulkReply(utils.ToCmdLine("SELECT", strconv.Itoa(ctx.dbIdx))).ToBytes()
|
data := protocol.MakeMultiBulkReply(utils.ToCmdLine("SELECT", strconv.Itoa(ctx.dbIdx))).ToBytes()
|
||||||
_, err = tmpFile.Write(data)
|
_, err = tmpFile.Write(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("tmp file rewrite failed: " + err.Error())
|
logger.Error("tmp file rewrite failed: " + err.Error())
|
||||||
@@ -153,7 +153,7 @@ func (handler *Handler) FinishRewrite(ctx *RewriteCtx) {
|
|||||||
handler.aofFile = aofFile
|
handler.aofFile = aofFile
|
||||||
|
|
||||||
// reset selected db 重新写入一次 select 指令保证 aof 中的数据库与 handler.currentDB 一致
|
// reset selected db 重新写入一次 select 指令保证 aof 中的数据库与 handler.currentDB 一致
|
||||||
data = reply.MakeMultiBulkReply(utils.ToCmdLine("SELECT", strconv.Itoa(handler.currentDB))).ToBytes()
|
data = protocol.MakeMultiBulkReply(utils.ToCmdLine("SELECT", strconv.Itoa(handler.currentDB))).ToBytes()
|
||||||
_, err = handler.aofFile.Write(data)
|
_, err = handler.aofFile.Write(data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
@@ -12,7 +12,7 @@ import (
|
|||||||
"github.com/hdt3213/godis/lib/consistenthash"
|
"github.com/hdt3213/godis/lib/consistenthash"
|
||||||
"github.com/hdt3213/godis/lib/idgenerator"
|
"github.com/hdt3213/godis/lib/idgenerator"
|
||||||
"github.com/hdt3213/godis/lib/logger"
|
"github.com/hdt3213/godis/lib/logger"
|
||||||
"github.com/hdt3213/godis/redis/reply"
|
"github.com/hdt3213/godis/redis/protocol"
|
||||||
"github.com/jolestar/go-commons-pool/v2"
|
"github.com/jolestar/go-commons-pool/v2"
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
"strconv"
|
"strconv"
|
||||||
@@ -97,7 +97,7 @@ func (cluster *Cluster) Exec(c redis.Connection, cmdLine [][]byte) (result redis
|
|||||||
defer func() {
|
defer func() {
|
||||||
if err := recover(); err != nil {
|
if err := recover(); err != nil {
|
||||||
logger.Warn(fmt.Sprintf("error occurs: %v\n%s", err, string(debug.Stack())))
|
logger.Warn(fmt.Sprintf("error occurs: %v\n%s", err, string(debug.Stack())))
|
||||||
result = &reply.UnknownErrReply{}
|
result = &protocol.UnknownErrReply{}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
cmdName := strings.ToLower(string(cmdLine[0]))
|
cmdName := strings.ToLower(string(cmdLine[0]))
|
||||||
@@ -105,27 +105,27 @@ func (cluster *Cluster) Exec(c redis.Connection, cmdLine [][]byte) (result redis
|
|||||||
return database2.Auth(c, cmdLine[1:])
|
return database2.Auth(c, cmdLine[1:])
|
||||||
}
|
}
|
||||||
if !isAuthenticated(c) {
|
if !isAuthenticated(c) {
|
||||||
return reply.MakeErrReply("NOAUTH Authentication required")
|
return protocol.MakeErrReply("NOAUTH Authentication required")
|
||||||
}
|
}
|
||||||
|
|
||||||
if cmdName == "multi" {
|
if cmdName == "multi" {
|
||||||
if len(cmdLine) != 1 {
|
if len(cmdLine) != 1 {
|
||||||
return reply.MakeArgNumErrReply(cmdName)
|
return protocol.MakeArgNumErrReply(cmdName)
|
||||||
}
|
}
|
||||||
return database2.StartMulti(c)
|
return database2.StartMulti(c)
|
||||||
} else if cmdName == "discard" {
|
} else if cmdName == "discard" {
|
||||||
if len(cmdLine) != 1 {
|
if len(cmdLine) != 1 {
|
||||||
return reply.MakeArgNumErrReply(cmdName)
|
return protocol.MakeArgNumErrReply(cmdName)
|
||||||
}
|
}
|
||||||
return database2.DiscardMulti(c)
|
return database2.DiscardMulti(c)
|
||||||
} else if cmdName == "exec" {
|
} else if cmdName == "exec" {
|
||||||
if len(cmdLine) != 1 {
|
if len(cmdLine) != 1 {
|
||||||
return reply.MakeArgNumErrReply(cmdName)
|
return protocol.MakeArgNumErrReply(cmdName)
|
||||||
}
|
}
|
||||||
return execMulti(cluster, c, nil)
|
return execMulti(cluster, c, nil)
|
||||||
} else if cmdName == "select" {
|
} else if cmdName == "select" {
|
||||||
if len(cmdLine) != 2 {
|
if len(cmdLine) != 2 {
|
||||||
return reply.MakeArgNumErrReply(cmdName)
|
return protocol.MakeArgNumErrReply(cmdName)
|
||||||
}
|
}
|
||||||
return execSelect(c, cmdLine)
|
return execSelect(c, cmdLine)
|
||||||
}
|
}
|
||||||
@@ -134,7 +134,7 @@ func (cluster *Cluster) Exec(c redis.Connection, cmdLine [][]byte) (result redis
|
|||||||
}
|
}
|
||||||
cmdFunc, ok := router[cmdName]
|
cmdFunc, ok := router[cmdName]
|
||||||
if !ok {
|
if !ok {
|
||||||
return reply.MakeErrReply("ERR unknown command '" + cmdName + "', or not supported in cluster mode")
|
return protocol.MakeErrReply("ERR unknown command '" + cmdName + "', or not supported in cluster mode")
|
||||||
}
|
}
|
||||||
result = cmdFunc(cluster, c, cmdLine)
|
result = cmdFunc(cluster, c, cmdLine)
|
||||||
return
|
return
|
||||||
@@ -178,11 +178,11 @@ func (cluster *Cluster) groupBy(keys []string) map[string][]string {
|
|||||||
func execSelect(c redis.Connection, args [][]byte) redis.Reply {
|
func execSelect(c redis.Connection, args [][]byte) redis.Reply {
|
||||||
dbIndex, err := strconv.Atoi(string(args[1]))
|
dbIndex, err := strconv.Atoi(string(args[1]))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reply.MakeErrReply("ERR invalid DB index")
|
return protocol.MakeErrReply("ERR invalid DB index")
|
||||||
}
|
}
|
||||||
if dbIndex >= config.Properties.Databases {
|
if dbIndex >= config.Properties.Databases {
|
||||||
return reply.MakeErrReply("ERR DB index is out of range")
|
return protocol.MakeErrReply("ERR DB index is out of range")
|
||||||
}
|
}
|
||||||
c.SelectDB(dbIndex)
|
c.SelectDB(dbIndex)
|
||||||
return reply.MakeOkReply()
|
return protocol.MakeOkReply()
|
||||||
}
|
}
|
||||||
|
@@ -6,7 +6,7 @@ import (
|
|||||||
"github.com/hdt3213/godis/interface/redis"
|
"github.com/hdt3213/godis/interface/redis"
|
||||||
"github.com/hdt3213/godis/lib/utils"
|
"github.com/hdt3213/godis/lib/utils"
|
||||||
"github.com/hdt3213/godis/redis/client"
|
"github.com/hdt3213/godis/redis/client"
|
||||||
"github.com/hdt3213/godis/redis/reply"
|
"github.com/hdt3213/godis/redis/protocol"
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -44,7 +44,7 @@ func (cluster *Cluster) relay(peer string, c redis.Connection, args [][]byte) re
|
|||||||
}
|
}
|
||||||
peerClient, err := cluster.getPeerClient(peer)
|
peerClient, err := cluster.getPeerClient(peer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reply.MakeErrReply(err.Error())
|
return protocol.MakeErrReply(err.Error())
|
||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
_ = cluster.returnPeerClient(peer, peerClient)
|
_ = cluster.returnPeerClient(peer, peerClient)
|
||||||
|
@@ -4,7 +4,7 @@ import (
|
|||||||
"github.com/hdt3213/godis/config"
|
"github.com/hdt3213/godis/config"
|
||||||
"github.com/hdt3213/godis/lib/utils"
|
"github.com/hdt3213/godis/lib/utils"
|
||||||
"github.com/hdt3213/godis/redis/connection"
|
"github.com/hdt3213/godis/redis/connection"
|
||||||
"github.com/hdt3213/godis/redis/reply/asserts"
|
"github.com/hdt3213/godis/redis/protocol/asserts"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -2,7 +2,7 @@ package cluster
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/hdt3213/godis/interface/redis"
|
"github.com/hdt3213/godis/interface/redis"
|
||||||
"github.com/hdt3213/godis/redis/reply"
|
"github.com/hdt3213/godis/redis/protocol"
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -10,7 +10,7 @@ import (
|
|||||||
// if the given writeKeys are distributed on different node, Del will use try-commit-catch to remove them
|
// if the given writeKeys are distributed on different node, Del will use try-commit-catch to remove them
|
||||||
func Del(cluster *Cluster, c redis.Connection, args [][]byte) redis.Reply {
|
func Del(cluster *Cluster, c redis.Connection, args [][]byte) redis.Reply {
|
||||||
if len(args) < 2 {
|
if len(args) < 2 {
|
||||||
return reply.MakeErrReply("ERR wrong number of arguments for 'del' command")
|
return protocol.MakeErrReply("ERR wrong number of arguments for 'del' command")
|
||||||
}
|
}
|
||||||
keys := make([]string, len(args)-1)
|
keys := make([]string, len(args)-1)
|
||||||
for i := 1; i < len(args); i++ {
|
for i := 1; i < len(args); i++ {
|
||||||
@@ -36,7 +36,7 @@ func Del(cluster *Cluster, c redis.Connection, args [][]byte) redis.Reply {
|
|||||||
} else {
|
} else {
|
||||||
resp = cluster.relay(peer, c, makeArgs("Prepare", peerArgs...))
|
resp = cluster.relay(peer, c, makeArgs("Prepare", peerArgs...))
|
||||||
}
|
}
|
||||||
if reply.IsErrorReply(resp) {
|
if protocol.IsErrorReply(resp) {
|
||||||
errReply = resp
|
errReply = resp
|
||||||
rollback = true
|
rollback = true
|
||||||
break
|
break
|
||||||
@@ -56,10 +56,10 @@ func Del(cluster *Cluster, c redis.Connection, args [][]byte) redis.Reply {
|
|||||||
if !rollback {
|
if !rollback {
|
||||||
var deleted int64 = 0
|
var deleted int64 = 0
|
||||||
for _, resp := range respList {
|
for _, resp := range respList {
|
||||||
intResp := resp.(*reply.IntReply)
|
intResp := resp.(*protocol.IntReply)
|
||||||
deleted += intResp.Code
|
deleted += intResp.Code
|
||||||
}
|
}
|
||||||
return reply.MakeIntReply(int64(deleted))
|
return protocol.MakeIntReply(int64(deleted))
|
||||||
}
|
}
|
||||||
return errReply
|
return errReply
|
||||||
}
|
}
|
||||||
|
@@ -2,7 +2,7 @@ package cluster
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/hdt3213/godis/redis/connection"
|
"github.com/hdt3213/godis/redis/connection"
|
||||||
"github.com/hdt3213/godis/redis/reply/asserts"
|
"github.com/hdt3213/godis/redis/protocol/asserts"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -2,23 +2,23 @@ package cluster
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/hdt3213/godis/interface/redis"
|
"github.com/hdt3213/godis/interface/redis"
|
||||||
"github.com/hdt3213/godis/redis/reply"
|
"github.com/hdt3213/godis/redis/protocol"
|
||||||
)
|
)
|
||||||
|
|
||||||
// FlushDB removes all data in current database
|
// FlushDB removes all data in current database
|
||||||
func FlushDB(cluster *Cluster, c redis.Connection, args [][]byte) redis.Reply {
|
func FlushDB(cluster *Cluster, c redis.Connection, args [][]byte) redis.Reply {
|
||||||
replies := cluster.broadcast(c, args)
|
replies := cluster.broadcast(c, args)
|
||||||
var errReply reply.ErrorReply
|
var errReply protocol.ErrorReply
|
||||||
for _, v := range replies {
|
for _, v := range replies {
|
||||||
if reply.IsErrorReply(v) {
|
if protocol.IsErrorReply(v) {
|
||||||
errReply = v.(reply.ErrorReply)
|
errReply = v.(protocol.ErrorReply)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if errReply == nil {
|
if errReply == nil {
|
||||||
return &reply.OkReply{}
|
return &protocol.OkReply{}
|
||||||
}
|
}
|
||||||
return reply.MakeErrReply("error occurs: " + errReply.Error())
|
return protocol.MakeErrReply("error occurs: " + errReply.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
// FlushAll removes all data in cluster
|
// FlushAll removes all data in cluster
|
||||||
|
@@ -4,7 +4,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"github.com/hdt3213/godis/interface/redis"
|
"github.com/hdt3213/godis/interface/redis"
|
||||||
"github.com/hdt3213/godis/lib/utils"
|
"github.com/hdt3213/godis/lib/utils"
|
||||||
"github.com/hdt3213/godis/redis/reply"
|
"github.com/hdt3213/godis/redis/protocol"
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -13,7 +13,7 @@ const keyExistsErr = "key exists"
|
|||||||
// MGet atomically get multi key-value from cluster, writeKeys can be distributed on any node
|
// MGet atomically get multi key-value from cluster, writeKeys can be distributed on any node
|
||||||
func MGet(cluster *Cluster, c redis.Connection, cmdLine CmdLine) redis.Reply {
|
func MGet(cluster *Cluster, c redis.Connection, cmdLine CmdLine) redis.Reply {
|
||||||
if len(cmdLine) < 2 {
|
if len(cmdLine) < 2 {
|
||||||
return reply.MakeErrReply("ERR wrong number of arguments for 'mget' command")
|
return protocol.MakeErrReply("ERR wrong number of arguments for 'mget' command")
|
||||||
}
|
}
|
||||||
keys := make([]string, len(cmdLine)-1)
|
keys := make([]string, len(cmdLine)-1)
|
||||||
for i := 1; i < len(cmdLine); i++ {
|
for i := 1; i < len(cmdLine); i++ {
|
||||||
@@ -24,11 +24,11 @@ func MGet(cluster *Cluster, c redis.Connection, cmdLine CmdLine) redis.Reply {
|
|||||||
groupMap := cluster.groupBy(keys)
|
groupMap := cluster.groupBy(keys)
|
||||||
for peer, group := range groupMap {
|
for peer, group := range groupMap {
|
||||||
resp := cluster.relay(peer, c, makeArgs("MGET", group...))
|
resp := cluster.relay(peer, c, makeArgs("MGET", group...))
|
||||||
if reply.IsErrorReply(resp) {
|
if protocol.IsErrorReply(resp) {
|
||||||
errReply := resp.(reply.ErrorReply)
|
errReply := resp.(protocol.ErrorReply)
|
||||||
return reply.MakeErrReply(fmt.Sprintf("ERR during get %s occurs: %v", group[0], errReply.Error()))
|
return protocol.MakeErrReply(fmt.Sprintf("ERR during get %s occurs: %v", group[0], errReply.Error()))
|
||||||
}
|
}
|
||||||
arrReply, _ := resp.(*reply.MultiBulkReply)
|
arrReply, _ := resp.(*protocol.MultiBulkReply)
|
||||||
for i, v := range arrReply.Args {
|
for i, v := range arrReply.Args {
|
||||||
key := group[i]
|
key := group[i]
|
||||||
resultMap[key] = v
|
resultMap[key] = v
|
||||||
@@ -38,14 +38,14 @@ func MGet(cluster *Cluster, c redis.Connection, cmdLine CmdLine) redis.Reply {
|
|||||||
for i, k := range keys {
|
for i, k := range keys {
|
||||||
result[i] = resultMap[k]
|
result[i] = resultMap[k]
|
||||||
}
|
}
|
||||||
return reply.MakeMultiBulkReply(result)
|
return protocol.MakeMultiBulkReply(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
// MSet atomically sets multi key-value in cluster, writeKeys can be distributed on any node
|
// MSet atomically sets multi key-value in cluster, writeKeys can be distributed on any node
|
||||||
func MSet(cluster *Cluster, c redis.Connection, cmdLine CmdLine) redis.Reply {
|
func MSet(cluster *Cluster, c redis.Connection, cmdLine CmdLine) redis.Reply {
|
||||||
argCount := len(cmdLine) - 1
|
argCount := len(cmdLine) - 1
|
||||||
if argCount%2 != 0 || argCount < 1 {
|
if argCount%2 != 0 || argCount < 1 {
|
||||||
return reply.MakeErrReply("ERR wrong number of arguments for 'mset' command")
|
return protocol.MakeErrReply("ERR wrong number of arguments for 'mset' command")
|
||||||
}
|
}
|
||||||
|
|
||||||
size := argCount / 2
|
size := argCount / 2
|
||||||
@@ -79,7 +79,7 @@ func MSet(cluster *Cluster, c redis.Connection, cmdLine CmdLine) redis.Reply {
|
|||||||
} else {
|
} else {
|
||||||
resp = cluster.relay(peer, c, makeArgs("Prepare", peerArgs...))
|
resp = cluster.relay(peer, c, makeArgs("Prepare", peerArgs...))
|
||||||
}
|
}
|
||||||
if reply.IsErrorReply(resp) {
|
if protocol.IsErrorReply(resp) {
|
||||||
errReply = resp
|
errReply = resp
|
||||||
rollback = true
|
rollback = true
|
||||||
break
|
break
|
||||||
@@ -93,7 +93,7 @@ func MSet(cluster *Cluster, c redis.Connection, cmdLine CmdLine) redis.Reply {
|
|||||||
rollback = errReply != nil
|
rollback = errReply != nil
|
||||||
}
|
}
|
||||||
if !rollback {
|
if !rollback {
|
||||||
return &reply.OkReply{}
|
return &protocol.OkReply{}
|
||||||
}
|
}
|
||||||
return errReply
|
return errReply
|
||||||
|
|
||||||
@@ -103,7 +103,7 @@ func MSet(cluster *Cluster, c redis.Connection, cmdLine CmdLine) redis.Reply {
|
|||||||
func MSetNX(cluster *Cluster, c redis.Connection, cmdLine CmdLine) redis.Reply {
|
func MSetNX(cluster *Cluster, c redis.Connection, cmdLine CmdLine) redis.Reply {
|
||||||
argCount := len(cmdLine) - 1
|
argCount := len(cmdLine) - 1
|
||||||
if argCount%2 != 0 || argCount < 1 {
|
if argCount%2 != 0 || argCount < 1 {
|
||||||
return reply.MakeErrReply("ERR wrong number of arguments for 'msetnx' command")
|
return protocol.MakeErrReply("ERR wrong number of arguments for 'msetnx' command")
|
||||||
}
|
}
|
||||||
|
|
||||||
size := argCount / 2
|
size := argCount / 2
|
||||||
@@ -139,10 +139,10 @@ func MSetNX(cluster *Cluster, c redis.Connection, cmdLine CmdLine) redis.Reply {
|
|||||||
} else {
|
} else {
|
||||||
resp = cluster.relay(peer, c, makeArgs("Prepare", peerArgs...))
|
resp = cluster.relay(peer, c, makeArgs("Prepare", peerArgs...))
|
||||||
}
|
}
|
||||||
if reply.IsErrorReply(resp) {
|
if protocol.IsErrorReply(resp) {
|
||||||
re := resp.(reply.ErrorReply)
|
re := resp.(protocol.ErrorReply)
|
||||||
if re.Error() == keyExistsErr {
|
if re.Error() == keyExistsErr {
|
||||||
errReply = reply.MakeIntReply(0)
|
errReply = protocol.MakeIntReply(0)
|
||||||
} else {
|
} else {
|
||||||
errReply = resp
|
errReply = resp
|
||||||
}
|
}
|
||||||
@@ -158,7 +158,7 @@ func MSetNX(cluster *Cluster, c redis.Connection, cmdLine CmdLine) redis.Reply {
|
|||||||
_, errReply = requestCommit(cluster, c, txID, groupMap)
|
_, errReply = requestCommit(cluster, c, txID, groupMap)
|
||||||
rollback = errReply != nil
|
rollback = errReply != nil
|
||||||
if !rollback {
|
if !rollback {
|
||||||
return reply.MakeIntReply(1)
|
return protocol.MakeIntReply(1)
|
||||||
}
|
}
|
||||||
return errReply
|
return errReply
|
||||||
}
|
}
|
||||||
@@ -166,7 +166,7 @@ func MSetNX(cluster *Cluster, c redis.Connection, cmdLine CmdLine) redis.Reply {
|
|||||||
func prepareMSetNx(cluster *Cluster, conn redis.Connection, cmdLine CmdLine) redis.Reply {
|
func prepareMSetNx(cluster *Cluster, conn redis.Connection, cmdLine CmdLine) redis.Reply {
|
||||||
args := cmdLine[1:]
|
args := cmdLine[1:]
|
||||||
if len(args)%2 != 0 {
|
if len(args)%2 != 0 {
|
||||||
return reply.MakeSyntaxErrReply()
|
return protocol.MakeSyntaxErrReply()
|
||||||
}
|
}
|
||||||
size := len(args) / 2
|
size := len(args) / 2
|
||||||
values := make([][]byte, size)
|
values := make([][]byte, size)
|
||||||
@@ -176,14 +176,14 @@ func prepareMSetNx(cluster *Cluster, conn redis.Connection, cmdLine CmdLine) red
|
|||||||
values[i] = args[2*i+1]
|
values[i] = args[2*i+1]
|
||||||
}
|
}
|
||||||
re := cluster.db.ExecWithLock(conn, utils.ToCmdLine2("ExistIn", keys...))
|
re := cluster.db.ExecWithLock(conn, utils.ToCmdLine2("ExistIn", keys...))
|
||||||
if reply.IsErrorReply(re) {
|
if protocol.IsErrorReply(re) {
|
||||||
return re
|
return re
|
||||||
}
|
}
|
||||||
_, ok := re.(*reply.EmptyMultiBulkReply)
|
_, ok := re.(*protocol.EmptyMultiBulkReply)
|
||||||
if !ok {
|
if !ok {
|
||||||
return reply.MakeErrReply(keyExistsErr)
|
return protocol.MakeErrReply(keyExistsErr)
|
||||||
}
|
}
|
||||||
return reply.MakeOkReply()
|
return protocol.MakeOkReply()
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@@ -2,7 +2,7 @@ package cluster
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/hdt3213/godis/redis/connection"
|
"github.com/hdt3213/godis/redis/connection"
|
||||||
"github.com/hdt3213/godis/redis/reply/asserts"
|
"github.com/hdt3213/godis/redis/protocol/asserts"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -4,7 +4,7 @@ import (
|
|||||||
"github.com/hdt3213/godis/database"
|
"github.com/hdt3213/godis/database"
|
||||||
"github.com/hdt3213/godis/interface/redis"
|
"github.com/hdt3213/godis/interface/redis"
|
||||||
"github.com/hdt3213/godis/lib/utils"
|
"github.com/hdt3213/godis/lib/utils"
|
||||||
"github.com/hdt3213/godis/redis/reply"
|
"github.com/hdt3213/godis/redis/protocol"
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -16,7 +16,7 @@ var relayMultiBytes = []byte(relayMulti)
|
|||||||
// cmdLine == []string{"exec"}
|
// cmdLine == []string{"exec"}
|
||||||
func execMulti(cluster *Cluster, conn redis.Connection, cmdLine CmdLine) redis.Reply {
|
func execMulti(cluster *Cluster, conn redis.Connection, cmdLine CmdLine) redis.Reply {
|
||||||
if !conn.InMultiState() {
|
if !conn.InMultiState() {
|
||||||
return reply.MakeErrReply("ERR EXEC without MULTI")
|
return protocol.MakeErrReply("ERR EXEC without MULTI")
|
||||||
}
|
}
|
||||||
defer conn.SetMultiState(false)
|
defer conn.SetMultiState(false)
|
||||||
cmdLines := conn.GetQueuedCmdLine()
|
cmdLines := conn.GetQueuedCmdLine()
|
||||||
@@ -40,7 +40,7 @@ func execMulti(cluster *Cluster, conn redis.Connection, cmdLine CmdLine) redis.R
|
|||||||
}
|
}
|
||||||
groupMap := cluster.groupBy(keys)
|
groupMap := cluster.groupBy(keys)
|
||||||
if len(groupMap) > 1 {
|
if len(groupMap) > 1 {
|
||||||
return reply.MakeErrReply("ERR MULTI commands transaction must within one slot in cluster mode")
|
return protocol.MakeErrReply("ERR MULTI commands transaction must within one slot in cluster mode")
|
||||||
}
|
}
|
||||||
var peer string
|
var peer string
|
||||||
// assert len(groupMap) == 1
|
// assert len(groupMap) == 1
|
||||||
@@ -48,7 +48,7 @@ func execMulti(cluster *Cluster, conn redis.Connection, cmdLine CmdLine) redis.R
|
|||||||
peer = p
|
peer = p
|
||||||
}
|
}
|
||||||
|
|
||||||
// out parser not support reply.MultiRawReply, so we have to encode it
|
// out parser not support protocol.MultiRawReply, so we have to encode it
|
||||||
if peer == cluster.self {
|
if peer == cluster.self {
|
||||||
return cluster.db.ExecMulti(conn, watching, cmdLines)
|
return cluster.db.ExecMulti(conn, watching, cmdLines)
|
||||||
}
|
}
|
||||||
@@ -78,40 +78,40 @@ func execMultiOnOtherNode(cluster *Cluster, conn redis.Connection, peer string,
|
|||||||
} else {
|
} else {
|
||||||
rawRelayResult = cluster.relay(peer, conn, relayCmdLine)
|
rawRelayResult = cluster.relay(peer, conn, relayCmdLine)
|
||||||
}
|
}
|
||||||
if reply.IsErrorReply(rawRelayResult) {
|
if protocol.IsErrorReply(rawRelayResult) {
|
||||||
return rawRelayResult
|
return rawRelayResult
|
||||||
}
|
}
|
||||||
_, ok := rawRelayResult.(*reply.EmptyMultiBulkReply)
|
_, ok := rawRelayResult.(*protocol.EmptyMultiBulkReply)
|
||||||
if ok {
|
if ok {
|
||||||
return rawRelayResult
|
return rawRelayResult
|
||||||
}
|
}
|
||||||
relayResult, ok := rawRelayResult.(*reply.MultiBulkReply)
|
relayResult, ok := rawRelayResult.(*protocol.MultiBulkReply)
|
||||||
if !ok {
|
if !ok {
|
||||||
return reply.MakeErrReply("execute failed")
|
return protocol.MakeErrReply("execute failed")
|
||||||
}
|
}
|
||||||
rep, err := parseEncodedMultiRawReply(relayResult.Args)
|
rep, err := parseEncodedMultiRawReply(relayResult.Args)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reply.MakeErrReply(err.Error())
|
return protocol.MakeErrReply(err.Error())
|
||||||
}
|
}
|
||||||
return rep
|
return rep
|
||||||
}
|
}
|
||||||
|
|
||||||
// execRelayedMulti execute relayed multi commands transaction
|
// execRelayedMulti execute relayed multi commands transaction
|
||||||
// cmdLine format: _multi watch-cmdLine base64ed-cmdLine
|
// cmdLine format: _multi watch-cmdLine base64ed-cmdLine
|
||||||
// result format: base64ed-reply list
|
// result format: base64ed-protocol list
|
||||||
func execRelayedMulti(cluster *Cluster, conn redis.Connection, cmdLine CmdLine) redis.Reply {
|
func execRelayedMulti(cluster *Cluster, conn redis.Connection, cmdLine CmdLine) redis.Reply {
|
||||||
if len(cmdLine) < 2 {
|
if len(cmdLine) < 2 {
|
||||||
return reply.MakeArgNumErrReply("_exec")
|
return protocol.MakeArgNumErrReply("_exec")
|
||||||
}
|
}
|
||||||
decoded, err := parseEncodedMultiRawReply(cmdLine[1:])
|
decoded, err := parseEncodedMultiRawReply(cmdLine[1:])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reply.MakeErrReply(err.Error())
|
return protocol.MakeErrReply(err.Error())
|
||||||
}
|
}
|
||||||
var txCmdLines []CmdLine
|
var txCmdLines []CmdLine
|
||||||
for _, rep := range decoded.Replies {
|
for _, rep := range decoded.Replies {
|
||||||
mbr, ok := rep.(*reply.MultiBulkReply)
|
mbr, ok := rep.(*protocol.MultiBulkReply)
|
||||||
if !ok {
|
if !ok {
|
||||||
return reply.MakeErrReply("exec failed")
|
return protocol.MakeErrReply("exec failed")
|
||||||
}
|
}
|
||||||
txCmdLines = append(txCmdLines, mbr.Args)
|
txCmdLines = append(txCmdLines, mbr.Args)
|
||||||
}
|
}
|
||||||
@@ -122,25 +122,25 @@ func execRelayedMulti(cluster *Cluster, conn redis.Connection, cmdLine CmdLine)
|
|||||||
verStr := string(watchCmdLine[i])
|
verStr := string(watchCmdLine[i])
|
||||||
ver, err := strconv.ParseUint(verStr, 10, 64)
|
ver, err := strconv.ParseUint(verStr, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reply.MakeErrReply("watching command line failed")
|
return protocol.MakeErrReply("watching command line failed")
|
||||||
}
|
}
|
||||||
watching[key] = uint32(ver)
|
watching[key] = uint32(ver)
|
||||||
}
|
}
|
||||||
rawResult := cluster.db.ExecMulti(conn, watching, txCmdLines[1:])
|
rawResult := cluster.db.ExecMulti(conn, watching, txCmdLines[1:])
|
||||||
_, ok := rawResult.(*reply.EmptyMultiBulkReply)
|
_, ok := rawResult.(*protocol.EmptyMultiBulkReply)
|
||||||
if ok {
|
if ok {
|
||||||
return rawResult
|
return rawResult
|
||||||
}
|
}
|
||||||
resultMBR, ok := rawResult.(*reply.MultiRawReply)
|
resultMBR, ok := rawResult.(*protocol.MultiRawReply)
|
||||||
if !ok {
|
if !ok {
|
||||||
return reply.MakeErrReply("exec failed")
|
return protocol.MakeErrReply("exec failed")
|
||||||
}
|
}
|
||||||
return encodeMultiRawReply(resultMBR)
|
return encodeMultiRawReply(resultMBR)
|
||||||
}
|
}
|
||||||
|
|
||||||
func execWatch(cluster *Cluster, conn redis.Connection, args [][]byte) redis.Reply {
|
func execWatch(cluster *Cluster, conn redis.Connection, args [][]byte) redis.Reply {
|
||||||
if len(args) < 2 {
|
if len(args) < 2 {
|
||||||
return reply.MakeArgNumErrReply("watch")
|
return protocol.MakeArgNumErrReply("watch")
|
||||||
}
|
}
|
||||||
args = args[1:]
|
args = args[1:]
|
||||||
watching := conn.GetWatching()
|
watching := conn.GetWatching()
|
||||||
@@ -148,14 +148,14 @@ func execWatch(cluster *Cluster, conn redis.Connection, args [][]byte) redis.Rep
|
|||||||
key := string(bkey)
|
key := string(bkey)
|
||||||
peer := cluster.peerPicker.PickNode(key)
|
peer := cluster.peerPicker.PickNode(key)
|
||||||
result := cluster.relay(peer, conn, utils.ToCmdLine("GetVer", key))
|
result := cluster.relay(peer, conn, utils.ToCmdLine("GetVer", key))
|
||||||
if reply.IsErrorReply(result) {
|
if protocol.IsErrorReply(result) {
|
||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
intResult, ok := result.(*reply.IntReply)
|
intResult, ok := result.(*protocol.IntReply)
|
||||||
if !ok {
|
if !ok {
|
||||||
return reply.MakeErrReply("get version failed")
|
return protocol.MakeErrReply("get version failed")
|
||||||
}
|
}
|
||||||
watching[key] = uint32(intResult.Code)
|
watching[key] = uint32(intResult.Code)
|
||||||
}
|
}
|
||||||
return reply.MakeOkReply()
|
return protocol.MakeOkReply()
|
||||||
}
|
}
|
||||||
|
@@ -4,13 +4,13 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"github.com/hdt3213/godis/redis/parser"
|
"github.com/hdt3213/godis/redis/parser"
|
||||||
"github.com/hdt3213/godis/redis/reply"
|
"github.com/hdt3213/godis/redis/protocol"
|
||||||
)
|
)
|
||||||
|
|
||||||
func encodeCmdLine(cmdLines []CmdLine) [][]byte {
|
func encodeCmdLine(cmdLines []CmdLine) [][]byte {
|
||||||
var result [][]byte
|
var result [][]byte
|
||||||
for _, line := range cmdLines {
|
for _, line := range cmdLines {
|
||||||
raw := reply.MakeMultiBulkReply(line).ToBytes()
|
raw := protocol.MakeMultiBulkReply(line).ToBytes()
|
||||||
encoded := make([]byte, base64.StdEncoding.EncodedLen(len(raw)))
|
encoded := make([]byte, base64.StdEncoding.EncodedLen(len(raw)))
|
||||||
base64.StdEncoding.Encode(encoded, raw)
|
base64.StdEncoding.Encode(encoded, raw)
|
||||||
result = append(result, encoded)
|
result = append(result, encoded)
|
||||||
@@ -18,7 +18,7 @@ func encodeCmdLine(cmdLines []CmdLine) [][]byte {
|
|||||||
return result
|
return result
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseEncodedMultiRawReply(args [][]byte) (*reply.MultiRawReply, error) {
|
func parseEncodedMultiRawReply(args [][]byte) (*protocol.MultiRawReply, error) {
|
||||||
cmdBuf := new(bytes.Buffer)
|
cmdBuf := new(bytes.Buffer)
|
||||||
for _, arg := range args {
|
for _, arg := range args {
|
||||||
dbuf := make([]byte, base64.StdEncoding.DecodedLen(len(arg)))
|
dbuf := make([]byte, base64.StdEncoding.DecodedLen(len(arg)))
|
||||||
@@ -30,12 +30,12 @@ func parseEncodedMultiRawReply(args [][]byte) (*reply.MultiRawReply, error) {
|
|||||||
}
|
}
|
||||||
cmds, err := parser.ParseBytes(cmdBuf.Bytes())
|
cmds, err := parser.ParseBytes(cmdBuf.Bytes())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, reply.MakeErrReply(err.Error())
|
return nil, protocol.MakeErrReply(err.Error())
|
||||||
}
|
}
|
||||||
return reply.MakeMultiRawReply(cmds), nil
|
return protocol.MakeMultiRawReply(cmds), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func encodeMultiRawReply(src *reply.MultiRawReply) *reply.MultiBulkReply {
|
func encodeMultiRawReply(src *protocol.MultiRawReply) *protocol.MultiBulkReply {
|
||||||
args := make([][]byte, 0, len(src.Replies))
|
args := make([][]byte, 0, len(src.Replies))
|
||||||
for _, rep := range src.Replies {
|
for _, rep := range src.Replies {
|
||||||
raw := rep.ToBytes()
|
raw := rep.ToBytes()
|
||||||
@@ -43,5 +43,5 @@ func encodeMultiRawReply(src *reply.MultiRawReply) *reply.MultiBulkReply {
|
|||||||
base64.StdEncoding.Encode(encoded, raw)
|
base64.StdEncoding.Encode(encoded, raw)
|
||||||
args = append(args, encoded)
|
args = append(args, encoded)
|
||||||
}
|
}
|
||||||
return reply.MakeMultiBulkReply(args)
|
return protocol.MakeMultiBulkReply(args)
|
||||||
}
|
}
|
||||||
|
@@ -3,8 +3,8 @@ package cluster
|
|||||||
import (
|
import (
|
||||||
"github.com/hdt3213/godis/lib/utils"
|
"github.com/hdt3213/godis/lib/utils"
|
||||||
"github.com/hdt3213/godis/redis/connection"
|
"github.com/hdt3213/godis/redis/connection"
|
||||||
"github.com/hdt3213/godis/redis/reply"
|
"github.com/hdt3213/godis/redis/protocol"
|
||||||
"github.com/hdt3213/godis/redis/reply/asserts"
|
"github.com/hdt3213/godis/redis/protocol/asserts"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -35,7 +35,7 @@ func TestEmptyMulti(t *testing.T) {
|
|||||||
asserts.AssertNotError(t, result)
|
asserts.AssertNotError(t, result)
|
||||||
result = testCluster.Exec(conn, utils.ToCmdLine("EXEC"))
|
result = testCluster.Exec(conn, utils.ToCmdLine("EXEC"))
|
||||||
asserts.AssertNotError(t, result)
|
asserts.AssertNotError(t, result)
|
||||||
mbr := result.(*reply.MultiRawReply)
|
mbr := result.(*protocol.MultiRawReply)
|
||||||
asserts.AssertStatusReply(t, mbr.Replies[0], "PONG")
|
asserts.AssertStatusReply(t, mbr.Replies[0], "PONG")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,7 +51,7 @@ func TestMultiExecOnOthers(t *testing.T) {
|
|||||||
|
|
||||||
cmdLines := conn.GetQueuedCmdLine()
|
cmdLines := conn.GetQueuedCmdLine()
|
||||||
rawResp := execMultiOnOtherNode(testCluster, conn, testCluster.self, nil, cmdLines)
|
rawResp := execMultiOnOtherNode(testCluster, conn, testCluster.self, nil, cmdLines)
|
||||||
rep := rawResp.(*reply.MultiRawReply)
|
rep := rawResp.(*protocol.MultiRawReply)
|
||||||
if len(rep.Replies) != 2 {
|
if len(rep.Replies) != 2 {
|
||||||
t.Errorf("expect 2 replies actual %d", len(rep.Replies))
|
t.Errorf("expect 2 replies actual %d", len(rep.Replies))
|
||||||
}
|
}
|
||||||
|
@@ -3,7 +3,7 @@ package cluster
|
|||||||
import (
|
import (
|
||||||
"github.com/hdt3213/godis/interface/redis"
|
"github.com/hdt3213/godis/interface/redis"
|
||||||
"github.com/hdt3213/godis/lib/logger"
|
"github.com/hdt3213/godis/lib/logger"
|
||||||
"github.com/hdt3213/godis/redis/reply"
|
"github.com/hdt3213/godis/redis/protocol"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -21,13 +21,13 @@ func Publish(cluster *Cluster, c redis.Connection, args [][]byte) redis.Reply {
|
|||||||
var count int64 = 0
|
var count int64 = 0
|
||||||
results := cluster.broadcast(c, args)
|
results := cluster.broadcast(c, args)
|
||||||
for _, val := range results {
|
for _, val := range results {
|
||||||
if errReply, ok := val.(reply.ErrorReply); ok {
|
if errReply, ok := val.(protocol.ErrorReply); ok {
|
||||||
logger.Error("publish occurs error: " + errReply.Error())
|
logger.Error("publish occurs error: " + errReply.Error())
|
||||||
} else if intReply, ok := val.(*reply.IntReply); ok {
|
} else if intReply, ok := val.(*protocol.IntReply); ok {
|
||||||
count += intReply.Code
|
count += intReply.Code
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return reply.MakeIntReply(count)
|
return protocol.MakeIntReply(count)
|
||||||
}
|
}
|
||||||
|
|
||||||
// onRelayedPublish receives publish command from peer, just publish to local subscribing clients, do not relay to peers
|
// onRelayedPublish receives publish command from peer, just publish to local subscribing clients, do not relay to peers
|
||||||
|
@@ -4,7 +4,7 @@ import (
|
|||||||
"github.com/hdt3213/godis/lib/utils"
|
"github.com/hdt3213/godis/lib/utils"
|
||||||
"github.com/hdt3213/godis/redis/connection"
|
"github.com/hdt3213/godis/redis/connection"
|
||||||
"github.com/hdt3213/godis/redis/parser"
|
"github.com/hdt3213/godis/redis/parser"
|
||||||
"github.com/hdt3213/godis/redis/reply/asserts"
|
"github.com/hdt3213/godis/redis/protocol/asserts"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -2,13 +2,13 @@ package cluster
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/hdt3213/godis/interface/redis"
|
"github.com/hdt3213/godis/interface/redis"
|
||||||
"github.com/hdt3213/godis/redis/reply"
|
"github.com/hdt3213/godis/redis/protocol"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Rename renames a key, the origin and the destination must within the same node
|
// Rename renames a key, the origin and the destination must within the same node
|
||||||
func Rename(cluster *Cluster, c redis.Connection, args [][]byte) redis.Reply {
|
func Rename(cluster *Cluster, c redis.Connection, args [][]byte) redis.Reply {
|
||||||
if len(args) != 3 {
|
if len(args) != 3 {
|
||||||
return reply.MakeErrReply("ERR wrong number of arguments for 'rename' command")
|
return protocol.MakeErrReply("ERR wrong number of arguments for 'rename' command")
|
||||||
}
|
}
|
||||||
src := string(args[1])
|
src := string(args[1])
|
||||||
dest := string(args[2])
|
dest := string(args[2])
|
||||||
@@ -17,7 +17,7 @@ func Rename(cluster *Cluster, c redis.Connection, args [][]byte) redis.Reply {
|
|||||||
destPeer := cluster.peerPicker.PickNode(dest)
|
destPeer := cluster.peerPicker.PickNode(dest)
|
||||||
|
|
||||||
if srcPeer != destPeer {
|
if srcPeer != destPeer {
|
||||||
return reply.MakeErrReply("ERR rename must within one slot in cluster mode")
|
return protocol.MakeErrReply("ERR rename must within one slot in cluster mode")
|
||||||
}
|
}
|
||||||
return cluster.relay(srcPeer, c, args)
|
return cluster.relay(srcPeer, c, args)
|
||||||
}
|
}
|
||||||
@@ -26,7 +26,7 @@ func Rename(cluster *Cluster, c redis.Connection, args [][]byte) redis.Reply {
|
|||||||
// The origin and the destination must within the same node
|
// The origin and the destination must within the same node
|
||||||
func RenameNx(cluster *Cluster, c redis.Connection, args [][]byte) redis.Reply {
|
func RenameNx(cluster *Cluster, c redis.Connection, args [][]byte) redis.Reply {
|
||||||
if len(args) != 3 {
|
if len(args) != 3 {
|
||||||
return reply.MakeErrReply("ERR wrong number of arguments for 'renamenx' command")
|
return protocol.MakeErrReply("ERR wrong number of arguments for 'renamenx' command")
|
||||||
}
|
}
|
||||||
src := string(args[1])
|
src := string(args[1])
|
||||||
dest := string(args[2])
|
dest := string(args[2])
|
||||||
@@ -35,7 +35,7 @@ func RenameNx(cluster *Cluster, c redis.Connection, args [][]byte) redis.Reply {
|
|||||||
destPeer := cluster.peerPicker.PickNode(dest)
|
destPeer := cluster.peerPicker.PickNode(dest)
|
||||||
|
|
||||||
if srcPeer != destPeer {
|
if srcPeer != destPeer {
|
||||||
return reply.MakeErrReply("ERR rename must within one slot in cluster mode")
|
return protocol.MakeErrReply("ERR rename must within one slot in cluster mode")
|
||||||
}
|
}
|
||||||
return cluster.relay(srcPeer, c, args)
|
return cluster.relay(srcPeer, c, args)
|
||||||
}
|
}
|
||||||
|
@@ -4,8 +4,8 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"github.com/hdt3213/godis/lib/utils"
|
"github.com/hdt3213/godis/lib/utils"
|
||||||
"github.com/hdt3213/godis/redis/connection"
|
"github.com/hdt3213/godis/redis/connection"
|
||||||
"github.com/hdt3213/godis/redis/reply"
|
"github.com/hdt3213/godis/redis/protocol"
|
||||||
"github.com/hdt3213/godis/redis/reply/asserts"
|
"github.com/hdt3213/godis/redis/protocol/asserts"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -18,7 +18,7 @@ func TestRename(t *testing.T) {
|
|||||||
newKey := key + utils.RandString(2)
|
newKey := key + utils.RandString(2)
|
||||||
testDB.Exec(conn, utils.ToCmdLine("SET", key, value, "ex", "1000"))
|
testDB.Exec(conn, utils.ToCmdLine("SET", key, value, "ex", "1000"))
|
||||||
result := Rename(testCluster, conn, utils.ToCmdLine("RENAME", key, newKey))
|
result := Rename(testCluster, conn, utils.ToCmdLine("RENAME", key, newKey))
|
||||||
if _, ok := result.(*reply.OkReply); !ok {
|
if _, ok := result.(*protocol.OkReply); !ok {
|
||||||
t.Error("expect ok")
|
t.Error("expect ok")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -28,9 +28,9 @@ func TestRename(t *testing.T) {
|
|||||||
asserts.AssertIntReply(t, result, 1)
|
asserts.AssertIntReply(t, result, 1)
|
||||||
// check ttl
|
// check ttl
|
||||||
result = testDB.Exec(conn, utils.ToCmdLine("TTL", newKey))
|
result = testDB.Exec(conn, utils.ToCmdLine("TTL", newKey))
|
||||||
intResult, ok := result.(*reply.IntReply)
|
intResult, ok := result.(*protocol.IntReply)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Error(fmt.Sprintf("expected int reply, actually %s", result.ToBytes()))
|
t.Error(fmt.Sprintf("expected int protocol, actually %s", result.ToBytes()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if intResult.Code <= 0 {
|
if intResult.Code <= 0 {
|
||||||
@@ -55,9 +55,9 @@ func TestRenameNx(t *testing.T) {
|
|||||||
|
|
||||||
asserts.AssertIntReply(t, result, 1)
|
asserts.AssertIntReply(t, result, 1)
|
||||||
result = testDB.Exec(conn, utils.ToCmdLine("TTL", newKey))
|
result = testDB.Exec(conn, utils.ToCmdLine("TTL", newKey))
|
||||||
intResult, ok := result.(*reply.IntReply)
|
intResult, ok := result.(*protocol.IntReply)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Error(fmt.Sprintf("expected int reply, actually %s", result.ToBytes()))
|
t.Error(fmt.Sprintf("expected int protocol, actually %s", result.ToBytes()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if intResult.Code <= 0 {
|
if intResult.Code <= 0 {
|
||||||
|
@@ -117,7 +117,7 @@ func makeRouter() map[string]CmdFunc {
|
|||||||
return routerMap
|
return routerMap
|
||||||
}
|
}
|
||||||
|
|
||||||
// relay command to responsible peer, and return its reply to client
|
// relay command to responsible peer, and return its protocol to client
|
||||||
func defaultFunc(cluster *Cluster, c redis.Connection, args [][]byte) redis.Reply {
|
func defaultFunc(cluster *Cluster, c redis.Connection, args [][]byte) redis.Reply {
|
||||||
key := string(args[1])
|
key := string(args[1])
|
||||||
peer := cluster.peerPicker.PickNode(key)
|
peer := cluster.peerPicker.PickNode(key)
|
||||||
|
@@ -6,7 +6,7 @@ import (
|
|||||||
"github.com/hdt3213/godis/interface/redis"
|
"github.com/hdt3213/godis/interface/redis"
|
||||||
"github.com/hdt3213/godis/lib/logger"
|
"github.com/hdt3213/godis/lib/logger"
|
||||||
"github.com/hdt3213/godis/lib/timewheel"
|
"github.com/hdt3213/godis/lib/timewheel"
|
||||||
"github.com/hdt3213/godis/redis/reply"
|
"github.com/hdt3213/godis/redis/protocol"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
@@ -122,7 +122,7 @@ func (tx *Transaction) rollback() error {
|
|||||||
// cmdLine: Prepare id cmdName args...
|
// cmdLine: Prepare id cmdName args...
|
||||||
func execPrepare(cluster *Cluster, c redis.Connection, cmdLine CmdLine) redis.Reply {
|
func execPrepare(cluster *Cluster, c redis.Connection, cmdLine CmdLine) redis.Reply {
|
||||||
if len(cmdLine) < 3 {
|
if len(cmdLine) < 3 {
|
||||||
return reply.MakeErrReply("ERR wrong number of arguments for 'prepare' command")
|
return protocol.MakeErrReply("ERR wrong number of arguments for 'prepare' command")
|
||||||
}
|
}
|
||||||
txID := string(cmdLine[1])
|
txID := string(cmdLine[1])
|
||||||
cmdName := strings.ToLower(string(cmdLine[2]))
|
cmdName := strings.ToLower(string(cmdLine[2]))
|
||||||
@@ -130,46 +130,46 @@ func execPrepare(cluster *Cluster, c redis.Connection, cmdLine CmdLine) redis.Re
|
|||||||
cluster.transactions.Put(txID, tx)
|
cluster.transactions.Put(txID, tx)
|
||||||
err := tx.prepare()
|
err := tx.prepare()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reply.MakeErrReply(err.Error())
|
return protocol.MakeErrReply(err.Error())
|
||||||
}
|
}
|
||||||
prepareFunc, ok := prepareFuncMap[cmdName]
|
prepareFunc, ok := prepareFuncMap[cmdName]
|
||||||
if ok {
|
if ok {
|
||||||
return prepareFunc(cluster, c, cmdLine[2:])
|
return prepareFunc(cluster, c, cmdLine[2:])
|
||||||
}
|
}
|
||||||
return &reply.OkReply{}
|
return &protocol.OkReply{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// execRollback rollbacks local transaction
|
// execRollback rollbacks local transaction
|
||||||
func execRollback(cluster *Cluster, c redis.Connection, cmdLine CmdLine) redis.Reply {
|
func execRollback(cluster *Cluster, c redis.Connection, cmdLine CmdLine) redis.Reply {
|
||||||
if len(cmdLine) != 2 {
|
if len(cmdLine) != 2 {
|
||||||
return reply.MakeErrReply("ERR wrong number of arguments for 'rollback' command")
|
return protocol.MakeErrReply("ERR wrong number of arguments for 'rollback' command")
|
||||||
}
|
}
|
||||||
txID := string(cmdLine[1])
|
txID := string(cmdLine[1])
|
||||||
raw, ok := cluster.transactions.Get(txID)
|
raw, ok := cluster.transactions.Get(txID)
|
||||||
if !ok {
|
if !ok {
|
||||||
return reply.MakeIntReply(0)
|
return protocol.MakeIntReply(0)
|
||||||
}
|
}
|
||||||
tx, _ := raw.(*Transaction)
|
tx, _ := raw.(*Transaction)
|
||||||
err := tx.rollback()
|
err := tx.rollback()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reply.MakeErrReply(err.Error())
|
return protocol.MakeErrReply(err.Error())
|
||||||
}
|
}
|
||||||
// clean transaction
|
// clean transaction
|
||||||
timewheel.Delay(waitBeforeCleanTx, "", func() {
|
timewheel.Delay(waitBeforeCleanTx, "", func() {
|
||||||
cluster.transactions.Remove(tx.id)
|
cluster.transactions.Remove(tx.id)
|
||||||
})
|
})
|
||||||
return reply.MakeIntReply(1)
|
return protocol.MakeIntReply(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// execCommit commits local transaction as a worker when receive execCommit command from coordinator
|
// execCommit commits local transaction as a worker when receive execCommit command from coordinator
|
||||||
func execCommit(cluster *Cluster, c redis.Connection, cmdLine CmdLine) redis.Reply {
|
func execCommit(cluster *Cluster, c redis.Connection, cmdLine CmdLine) redis.Reply {
|
||||||
if len(cmdLine) != 2 {
|
if len(cmdLine) != 2 {
|
||||||
return reply.MakeErrReply("ERR wrong number of arguments for 'commit' command")
|
return protocol.MakeErrReply("ERR wrong number of arguments for 'commit' command")
|
||||||
}
|
}
|
||||||
txID := string(cmdLine[1])
|
txID := string(cmdLine[1])
|
||||||
raw, ok := cluster.transactions.Get(txID)
|
raw, ok := cluster.transactions.Get(txID)
|
||||||
if !ok {
|
if !ok {
|
||||||
return reply.MakeIntReply(0)
|
return protocol.MakeIntReply(0)
|
||||||
}
|
}
|
||||||
tx, _ := raw.(*Transaction)
|
tx, _ := raw.(*Transaction)
|
||||||
|
|
||||||
@@ -178,10 +178,10 @@ func execCommit(cluster *Cluster, c redis.Connection, cmdLine CmdLine) redis.Rep
|
|||||||
|
|
||||||
result := cluster.db.ExecWithLock(c, tx.cmdLine)
|
result := cluster.db.ExecWithLock(c, tx.cmdLine)
|
||||||
|
|
||||||
if reply.IsErrorReply(result) {
|
if protocol.IsErrorReply(result) {
|
||||||
// failed
|
// failed
|
||||||
err2 := tx.rollback()
|
err2 := tx.rollback()
|
||||||
return reply.MakeErrReply(fmt.Sprintf("err occurs when rollback: %v, origin err: %s", err2, result))
|
return protocol.MakeErrReply(fmt.Sprintf("err occurs when rollback: %v, origin err: %s", err2, result))
|
||||||
}
|
}
|
||||||
// after committed
|
// after committed
|
||||||
tx.unLockKeys()
|
tx.unLockKeys()
|
||||||
@@ -195,8 +195,8 @@ func execCommit(cluster *Cluster, c redis.Connection, cmdLine CmdLine) redis.Rep
|
|||||||
}
|
}
|
||||||
|
|
||||||
// requestCommit commands all node to commit transaction as coordinator
|
// requestCommit commands all node to commit transaction as coordinator
|
||||||
func requestCommit(cluster *Cluster, c redis.Connection, txID int64, peers map[string][]string) ([]redis.Reply, reply.ErrorReply) {
|
func requestCommit(cluster *Cluster, c redis.Connection, txID int64, peers map[string][]string) ([]redis.Reply, protocol.ErrorReply) {
|
||||||
var errReply reply.ErrorReply
|
var errReply protocol.ErrorReply
|
||||||
txIDStr := strconv.FormatInt(txID, 10)
|
txIDStr := strconv.FormatInt(txID, 10)
|
||||||
respList := make([]redis.Reply, 0, len(peers))
|
respList := make([]redis.Reply, 0, len(peers))
|
||||||
for peer := range peers {
|
for peer := range peers {
|
||||||
@@ -206,8 +206,8 @@ func requestCommit(cluster *Cluster, c redis.Connection, txID int64, peers map[s
|
|||||||
} else {
|
} else {
|
||||||
resp = cluster.relay(peer, c, makeArgs("commit", txIDStr))
|
resp = cluster.relay(peer, c, makeArgs("commit", txIDStr))
|
||||||
}
|
}
|
||||||
if reply.IsErrorReply(resp) {
|
if protocol.IsErrorReply(resp) {
|
||||||
errReply = resp.(reply.ErrorReply)
|
errReply = resp.(protocol.ErrorReply)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
respList = append(respList, resp)
|
respList = append(respList, resp)
|
||||||
|
@@ -2,7 +2,7 @@ package cluster
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/hdt3213/godis/redis/connection"
|
"github.com/hdt3213/godis/redis/connection"
|
||||||
"github.com/hdt3213/godis/redis/reply/asserts"
|
"github.com/hdt3213/godis/redis/protocol/asserts"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"strconv"
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
|
@@ -6,8 +6,8 @@ import (
|
|||||||
"github.com/hdt3213/godis/interface/redis"
|
"github.com/hdt3213/godis/interface/redis"
|
||||||
"github.com/hdt3213/godis/lib/utils"
|
"github.com/hdt3213/godis/lib/utils"
|
||||||
"github.com/hdt3213/godis/redis/connection"
|
"github.com/hdt3213/godis/redis/connection"
|
||||||
"github.com/hdt3213/godis/redis/reply"
|
"github.com/hdt3213/godis/redis/protocol"
|
||||||
"github.com/hdt3213/godis/redis/reply/asserts"
|
"github.com/hdt3213/godis/redis/protocol/asserts"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
@@ -59,9 +59,9 @@ func validateTestData(t *testing.T, db database.DB, dbIndex int, prefix string,
|
|||||||
ret = db.Exec(conn, utils.ToCmdLine("GET", key))
|
ret = db.Exec(conn, utils.ToCmdLine("GET", key))
|
||||||
asserts.AssertBulkReply(t, ret, key)
|
asserts.AssertBulkReply(t, ret, key)
|
||||||
ret = db.Exec(conn, utils.ToCmdLine("TTL", key))
|
ret = db.Exec(conn, utils.ToCmdLine("TTL", key))
|
||||||
intResult, ok := ret.(*reply.IntReply)
|
intResult, ok := ret.(*protocol.IntReply)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Errorf("expected int reply, actually %s", ret.ToBytes())
|
t.Errorf("expected int protocol, actually %s", ret.ToBytes())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if intResult.Code <= 0 || intResult.Code > 10000 {
|
if intResult.Code <= 0 || intResult.Code > 10000 {
|
||||||
|
@@ -8,7 +8,7 @@ import (
|
|||||||
"github.com/hdt3213/godis/interface/redis"
|
"github.com/hdt3213/godis/interface/redis"
|
||||||
"github.com/hdt3213/godis/lib/logger"
|
"github.com/hdt3213/godis/lib/logger"
|
||||||
"github.com/hdt3213/godis/lib/timewheel"
|
"github.com/hdt3213/godis/lib/timewheel"
|
||||||
"github.com/hdt3213/godis/redis/reply"
|
"github.com/hdt3213/godis/redis/protocol"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
@@ -83,28 +83,28 @@ func (db *DB) Exec(c redis.Connection, cmdLine [][]byte) redis.Reply {
|
|||||||
cmdName := strings.ToLower(string(cmdLine[0]))
|
cmdName := strings.ToLower(string(cmdLine[0]))
|
||||||
if cmdName == "multi" {
|
if cmdName == "multi" {
|
||||||
if len(cmdLine) != 1 {
|
if len(cmdLine) != 1 {
|
||||||
return reply.MakeArgNumErrReply(cmdName)
|
return protocol.MakeArgNumErrReply(cmdName)
|
||||||
}
|
}
|
||||||
return StartMulti(c)
|
return StartMulti(c)
|
||||||
} else if cmdName == "discard" {
|
} else if cmdName == "discard" {
|
||||||
if len(cmdLine) != 1 {
|
if len(cmdLine) != 1 {
|
||||||
return reply.MakeArgNumErrReply(cmdName)
|
return protocol.MakeArgNumErrReply(cmdName)
|
||||||
}
|
}
|
||||||
return DiscardMulti(c)
|
return DiscardMulti(c)
|
||||||
} else if cmdName == "exec" {
|
} else if cmdName == "exec" {
|
||||||
if len(cmdLine) != 1 {
|
if len(cmdLine) != 1 {
|
||||||
return reply.MakeArgNumErrReply(cmdName)
|
return protocol.MakeArgNumErrReply(cmdName)
|
||||||
}
|
}
|
||||||
return execMulti(db, c)
|
return execMulti(db, c)
|
||||||
} else if cmdName == "watch" {
|
} else if cmdName == "watch" {
|
||||||
if !validateArity(-2, cmdLine) {
|
if !validateArity(-2, cmdLine) {
|
||||||
return reply.MakeArgNumErrReply(cmdName)
|
return protocol.MakeArgNumErrReply(cmdName)
|
||||||
}
|
}
|
||||||
return Watch(db, c, cmdLine[1:])
|
return Watch(db, c, cmdLine[1:])
|
||||||
}
|
}
|
||||||
if c != nil && c.InMultiState() {
|
if c != nil && c.InMultiState() {
|
||||||
EnqueueCmd(c, cmdLine)
|
EnqueueCmd(c, cmdLine)
|
||||||
return reply.MakeQueuedReply()
|
return protocol.MakeQueuedReply()
|
||||||
}
|
}
|
||||||
|
|
||||||
return db.execNormalCommand(cmdLine)
|
return db.execNormalCommand(cmdLine)
|
||||||
@@ -114,10 +114,10 @@ func (db *DB) execNormalCommand(cmdLine [][]byte) redis.Reply {
|
|||||||
cmdName := strings.ToLower(string(cmdLine[0]))
|
cmdName := strings.ToLower(string(cmdLine[0]))
|
||||||
cmd, ok := cmdTable[cmdName]
|
cmd, ok := cmdTable[cmdName]
|
||||||
if !ok {
|
if !ok {
|
||||||
return reply.MakeErrReply("ERR unknown command '" + cmdName + "'")
|
return protocol.MakeErrReply("ERR unknown command '" + cmdName + "'")
|
||||||
}
|
}
|
||||||
if !validateArity(cmd.arity, cmdLine) {
|
if !validateArity(cmd.arity, cmdLine) {
|
||||||
return reply.MakeArgNumErrReply(cmdName)
|
return protocol.MakeArgNumErrReply(cmdName)
|
||||||
}
|
}
|
||||||
|
|
||||||
prepare := cmd.prepare
|
prepare := cmd.prepare
|
||||||
|
@@ -6,7 +6,7 @@ import (
|
|||||||
"github.com/hdt3213/godis/interface/redis"
|
"github.com/hdt3213/godis/interface/redis"
|
||||||
"github.com/hdt3213/godis/lib/geohash"
|
"github.com/hdt3213/godis/lib/geohash"
|
||||||
"github.com/hdt3213/godis/lib/utils"
|
"github.com/hdt3213/godis/lib/utils"
|
||||||
"github.com/hdt3213/godis/redis/reply"
|
"github.com/hdt3213/godis/redis/protocol"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
@@ -14,7 +14,7 @@ import (
|
|||||||
// execGeoAdd add a location into SortedSet
|
// execGeoAdd add a location into SortedSet
|
||||||
func execGeoAdd(db *DB, args [][]byte) redis.Reply {
|
func execGeoAdd(db *DB, args [][]byte) redis.Reply {
|
||||||
if len(args) < 4 || len(args)%3 != 1 {
|
if len(args) < 4 || len(args)%3 != 1 {
|
||||||
return reply.MakeErrReply("ERR wrong number of arguments for 'geoadd' command")
|
return protocol.MakeErrReply("ERR wrong number of arguments for 'geoadd' command")
|
||||||
}
|
}
|
||||||
key := string(args[0])
|
key := string(args[0])
|
||||||
size := (len(args) - 1) / 3
|
size := (len(args) - 1) / 3
|
||||||
@@ -24,14 +24,14 @@ func execGeoAdd(db *DB, args [][]byte) redis.Reply {
|
|||||||
latStr := string(args[3*i+2])
|
latStr := string(args[3*i+2])
|
||||||
lng, err := strconv.ParseFloat(lngStr, 64)
|
lng, err := strconv.ParseFloat(lngStr, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reply.MakeErrReply("ERR value is not a valid float")
|
return protocol.MakeErrReply("ERR value is not a valid float")
|
||||||
}
|
}
|
||||||
lat, err := strconv.ParseFloat(latStr, 64)
|
lat, err := strconv.ParseFloat(latStr, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reply.MakeErrReply("ERR value is not a valid float")
|
return protocol.MakeErrReply("ERR value is not a valid float")
|
||||||
}
|
}
|
||||||
if lat < -90 || lat > 90 || lng < -180 || lng > 180 {
|
if lat < -90 || lat > 90 || lng < -180 || lng > 180 {
|
||||||
return reply.MakeErrReply(fmt.Sprintf("ERR invalid longitude,latitude pair %s,%s", latStr, lngStr))
|
return protocol.MakeErrReply(fmt.Sprintf("ERR invalid longitude,latitude pair %s,%s", latStr, lngStr))
|
||||||
}
|
}
|
||||||
code := float64(geohash.Encode(lat, lng))
|
code := float64(geohash.Encode(lat, lng))
|
||||||
elements[i] = &sortedset.Element{
|
elements[i] = &sortedset.Element{
|
||||||
@@ -53,7 +53,7 @@ func execGeoAdd(db *DB, args [][]byte) redis.Reply {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
db.addAof(utils.ToCmdLine3("geoadd", args...))
|
db.addAof(utils.ToCmdLine3("geoadd", args...))
|
||||||
return reply.MakeIntReply(int64(i))
|
return protocol.MakeIntReply(int64(i))
|
||||||
}
|
}
|
||||||
|
|
||||||
func undoGeoAdd(db *DB, args [][]byte) []CmdLine {
|
func undoGeoAdd(db *DB, args [][]byte) []CmdLine {
|
||||||
@@ -70,7 +70,7 @@ func undoGeoAdd(db *DB, args [][]byte) []CmdLine {
|
|||||||
func execGeoPos(db *DB, args [][]byte) redis.Reply {
|
func execGeoPos(db *DB, args [][]byte) redis.Reply {
|
||||||
// parse args
|
// parse args
|
||||||
if len(args) < 1 {
|
if len(args) < 1 {
|
||||||
return reply.MakeErrReply("ERR wrong number of arguments for 'geopos' command")
|
return protocol.MakeErrReply("ERR wrong number of arguments for 'geopos' command")
|
||||||
}
|
}
|
||||||
key := string(args[0])
|
key := string(args[0])
|
||||||
sortedSet, errReply := db.getAsSortedSet(key)
|
sortedSet, errReply := db.getAsSortedSet(key)
|
||||||
@@ -78,7 +78,7 @@ func execGeoPos(db *DB, args [][]byte) redis.Reply {
|
|||||||
return errReply
|
return errReply
|
||||||
}
|
}
|
||||||
if sortedSet == nil {
|
if sortedSet == nil {
|
||||||
return &reply.NullBulkReply{}
|
return &protocol.NullBulkReply{}
|
||||||
}
|
}
|
||||||
|
|
||||||
positions := make([]redis.Reply, len(args)-1)
|
positions := make([]redis.Reply, len(args)-1)
|
||||||
@@ -86,24 +86,24 @@ func execGeoPos(db *DB, args [][]byte) redis.Reply {
|
|||||||
member := string(args[i+1])
|
member := string(args[i+1])
|
||||||
elem, exists := sortedSet.Get(member)
|
elem, exists := sortedSet.Get(member)
|
||||||
if !exists {
|
if !exists {
|
||||||
positions[i] = &reply.EmptyMultiBulkReply{}
|
positions[i] = &protocol.EmptyMultiBulkReply{}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
lat, lng := geohash.Decode(uint64(elem.Score))
|
lat, lng := geohash.Decode(uint64(elem.Score))
|
||||||
lngStr := strconv.FormatFloat(lng, 'f', -1, 64)
|
lngStr := strconv.FormatFloat(lng, 'f', -1, 64)
|
||||||
latStr := strconv.FormatFloat(lat, 'f', -1, 64)
|
latStr := strconv.FormatFloat(lat, 'f', -1, 64)
|
||||||
positions[i] = reply.MakeMultiBulkReply([][]byte{
|
positions[i] = protocol.MakeMultiBulkReply([][]byte{
|
||||||
[]byte(lngStr), []byte(latStr),
|
[]byte(lngStr), []byte(latStr),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
return reply.MakeMultiRawReply(positions)
|
return protocol.MakeMultiRawReply(positions)
|
||||||
}
|
}
|
||||||
|
|
||||||
// execGeoDist returns the distance between two locations
|
// execGeoDist returns the distance between two locations
|
||||||
func execGeoDist(db *DB, args [][]byte) redis.Reply {
|
func execGeoDist(db *DB, args [][]byte) redis.Reply {
|
||||||
// parse args
|
// parse args
|
||||||
if len(args) != 3 && len(args) != 4 {
|
if len(args) != 3 && len(args) != 4 {
|
||||||
return reply.MakeErrReply("ERR wrong number of arguments for 'geodist' command")
|
return protocol.MakeErrReply("ERR wrong number of arguments for 'geodist' command")
|
||||||
}
|
}
|
||||||
key := string(args[0])
|
key := string(args[0])
|
||||||
sortedSet, errReply := db.getAsSortedSet(key)
|
sortedSet, errReply := db.getAsSortedSet(key)
|
||||||
@@ -111,7 +111,7 @@ func execGeoDist(db *DB, args [][]byte) redis.Reply {
|
|||||||
return errReply
|
return errReply
|
||||||
}
|
}
|
||||||
if sortedSet == nil {
|
if sortedSet == nil {
|
||||||
return &reply.NullBulkReply{}
|
return &protocol.NullBulkReply{}
|
||||||
}
|
}
|
||||||
|
|
||||||
positions := make([][]float64, 2)
|
positions := make([][]float64, 2)
|
||||||
@@ -119,7 +119,7 @@ func execGeoDist(db *DB, args [][]byte) redis.Reply {
|
|||||||
member := string(args[i])
|
member := string(args[i])
|
||||||
elem, exists := sortedSet.Get(member)
|
elem, exists := sortedSet.Get(member)
|
||||||
if !exists {
|
if !exists {
|
||||||
return &reply.NullBulkReply{}
|
return &protocol.NullBulkReply{}
|
||||||
}
|
}
|
||||||
lat, lng := geohash.Decode(uint64(elem.Score))
|
lat, lng := geohash.Decode(uint64(elem.Score))
|
||||||
positions[i-1] = []float64{lat, lng}
|
positions[i-1] = []float64{lat, lng}
|
||||||
@@ -132,19 +132,19 @@ func execGeoDist(db *DB, args [][]byte) redis.Reply {
|
|||||||
switch unit {
|
switch unit {
|
||||||
case "m":
|
case "m":
|
||||||
disStr := strconv.FormatFloat(dis, 'f', -1, 64)
|
disStr := strconv.FormatFloat(dis, 'f', -1, 64)
|
||||||
return reply.MakeBulkReply([]byte(disStr))
|
return protocol.MakeBulkReply([]byte(disStr))
|
||||||
case "km":
|
case "km":
|
||||||
disStr := strconv.FormatFloat(dis/1000, 'f', -1, 64)
|
disStr := strconv.FormatFloat(dis/1000, 'f', -1, 64)
|
||||||
return reply.MakeBulkReply([]byte(disStr))
|
return protocol.MakeBulkReply([]byte(disStr))
|
||||||
}
|
}
|
||||||
return reply.MakeErrReply("ERR unsupported unit provided. please use m, km")
|
return protocol.MakeErrReply("ERR unsupported unit provided. please use m, km")
|
||||||
}
|
}
|
||||||
|
|
||||||
// execGeoHash return geo-hash-code of given position
|
// execGeoHash return geo-hash-code of given position
|
||||||
func execGeoHash(db *DB, args [][]byte) redis.Reply {
|
func execGeoHash(db *DB, args [][]byte) redis.Reply {
|
||||||
// parse args
|
// parse args
|
||||||
if len(args) < 1 {
|
if len(args) < 1 {
|
||||||
return reply.MakeErrReply("ERR wrong number of arguments for 'geohash' command")
|
return protocol.MakeErrReply("ERR wrong number of arguments for 'geohash' command")
|
||||||
}
|
}
|
||||||
|
|
||||||
key := string(args[0])
|
key := string(args[0])
|
||||||
@@ -153,7 +153,7 @@ func execGeoHash(db *DB, args [][]byte) redis.Reply {
|
|||||||
return errReply
|
return errReply
|
||||||
}
|
}
|
||||||
if sortedSet == nil {
|
if sortedSet == nil {
|
||||||
return &reply.NullBulkReply{}
|
return &protocol.NullBulkReply{}
|
||||||
}
|
}
|
||||||
|
|
||||||
strs := make([][]byte, len(args)-1)
|
strs := make([][]byte, len(args)-1)
|
||||||
@@ -161,20 +161,20 @@ func execGeoHash(db *DB, args [][]byte) redis.Reply {
|
|||||||
member := string(args[i+1])
|
member := string(args[i+1])
|
||||||
elem, exists := sortedSet.Get(member)
|
elem, exists := sortedSet.Get(member)
|
||||||
if !exists {
|
if !exists {
|
||||||
strs[i] = (&reply.EmptyMultiBulkReply{}).ToBytes()
|
strs[i] = (&protocol.EmptyMultiBulkReply{}).ToBytes()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
str := geohash.ToString(geohash.FromInt(uint64(elem.Score)))
|
str := geohash.ToString(geohash.FromInt(uint64(elem.Score)))
|
||||||
strs[i] = []byte(str)
|
strs[i] = []byte(str)
|
||||||
}
|
}
|
||||||
return reply.MakeMultiBulkReply(strs)
|
return protocol.MakeMultiBulkReply(strs)
|
||||||
}
|
}
|
||||||
|
|
||||||
// execGeoRadius returns members within max distance of given point
|
// execGeoRadius returns members within max distance of given point
|
||||||
func execGeoRadius(db *DB, args [][]byte) redis.Reply {
|
func execGeoRadius(db *DB, args [][]byte) redis.Reply {
|
||||||
// parse args
|
// parse args
|
||||||
if len(args) < 5 {
|
if len(args) < 5 {
|
||||||
return reply.MakeErrReply("ERR wrong number of arguments for 'georadius' command")
|
return protocol.MakeErrReply("ERR wrong number of arguments for 'georadius' command")
|
||||||
}
|
}
|
||||||
|
|
||||||
key := string(args[0])
|
key := string(args[0])
|
||||||
@@ -183,27 +183,27 @@ func execGeoRadius(db *DB, args [][]byte) redis.Reply {
|
|||||||
return errReply
|
return errReply
|
||||||
}
|
}
|
||||||
if sortedSet == nil {
|
if sortedSet == nil {
|
||||||
return &reply.NullBulkReply{}
|
return &protocol.NullBulkReply{}
|
||||||
}
|
}
|
||||||
|
|
||||||
lng, err := strconv.ParseFloat(string(args[1]), 64)
|
lng, err := strconv.ParseFloat(string(args[1]), 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reply.MakeErrReply("ERR value is not a valid float")
|
return protocol.MakeErrReply("ERR value is not a valid float")
|
||||||
}
|
}
|
||||||
lat, err := strconv.ParseFloat(string(args[2]), 64)
|
lat, err := strconv.ParseFloat(string(args[2]), 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reply.MakeErrReply("ERR value is not a valid float")
|
return protocol.MakeErrReply("ERR value is not a valid float")
|
||||||
}
|
}
|
||||||
radius, err := strconv.ParseFloat(string(args[3]), 64)
|
radius, err := strconv.ParseFloat(string(args[3]), 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reply.MakeErrReply("ERR value is not a valid float")
|
return protocol.MakeErrReply("ERR value is not a valid float")
|
||||||
}
|
}
|
||||||
unit := strings.ToLower(string(args[4]))
|
unit := strings.ToLower(string(args[4]))
|
||||||
if unit == "m" {
|
if unit == "m" {
|
||||||
} else if unit == "km" {
|
} else if unit == "km" {
|
||||||
radius *= 1000
|
radius *= 1000
|
||||||
} else {
|
} else {
|
||||||
return reply.MakeErrReply("ERR unsupported unit provided. please use m, km")
|
return protocol.MakeErrReply("ERR unsupported unit provided. please use m, km")
|
||||||
}
|
}
|
||||||
return geoRadius0(sortedSet, lat, lng, radius)
|
return geoRadius0(sortedSet, lat, lng, radius)
|
||||||
}
|
}
|
||||||
@@ -212,7 +212,7 @@ func execGeoRadius(db *DB, args [][]byte) redis.Reply {
|
|||||||
func execGeoRadiusByMember(db *DB, args [][]byte) redis.Reply {
|
func execGeoRadiusByMember(db *DB, args [][]byte) redis.Reply {
|
||||||
// parse args
|
// parse args
|
||||||
if len(args) < 3 {
|
if len(args) < 3 {
|
||||||
return reply.MakeErrReply("ERR wrong number of arguments for 'georadiusbymember' command")
|
return protocol.MakeErrReply("ERR wrong number of arguments for 'georadiusbymember' command")
|
||||||
}
|
}
|
||||||
|
|
||||||
key := string(args[0])
|
key := string(args[0])
|
||||||
@@ -221,19 +221,19 @@ func execGeoRadiusByMember(db *DB, args [][]byte) redis.Reply {
|
|||||||
return errReply
|
return errReply
|
||||||
}
|
}
|
||||||
if sortedSet == nil {
|
if sortedSet == nil {
|
||||||
return &reply.NullBulkReply{}
|
return &protocol.NullBulkReply{}
|
||||||
}
|
}
|
||||||
|
|
||||||
member := string(args[1])
|
member := string(args[1])
|
||||||
elem, ok := sortedSet.Get(member)
|
elem, ok := sortedSet.Get(member)
|
||||||
if !ok {
|
if !ok {
|
||||||
return &reply.NullBulkReply{}
|
return &protocol.NullBulkReply{}
|
||||||
}
|
}
|
||||||
lat, lng := geohash.Decode(uint64(elem.Score))
|
lat, lng := geohash.Decode(uint64(elem.Score))
|
||||||
|
|
||||||
radius, err := strconv.ParseFloat(string(args[2]), 64)
|
radius, err := strconv.ParseFloat(string(args[2]), 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reply.MakeErrReply("ERR value is not a valid float")
|
return protocol.MakeErrReply("ERR value is not a valid float")
|
||||||
}
|
}
|
||||||
if len(args) > 3 {
|
if len(args) > 3 {
|
||||||
unit := strings.ToLower(string(args[3]))
|
unit := strings.ToLower(string(args[3]))
|
||||||
@@ -241,7 +241,7 @@ func execGeoRadiusByMember(db *DB, args [][]byte) redis.Reply {
|
|||||||
} else if unit == "km" {
|
} else if unit == "km" {
|
||||||
radius *= 1000
|
radius *= 1000
|
||||||
} else {
|
} else {
|
||||||
return reply.MakeErrReply("ERR unsupported unit provided. please use m, km")
|
return protocol.MakeErrReply("ERR unsupported unit provided. please use m, km")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return geoRadius0(sortedSet, lat, lng, radius)
|
return geoRadius0(sortedSet, lat, lng, radius)
|
||||||
@@ -258,7 +258,7 @@ func geoRadius0(sortedSet *sortedset.SortedSet, lat float64, lng float64, radius
|
|||||||
members = append(members, []byte(elem.Member))
|
members = append(members, []byte(elem.Member))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return reply.MakeMultiBulkReply(members)
|
return protocol.MakeMultiBulkReply(members)
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@@ -3,8 +3,8 @@ package database
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/hdt3213/godis/lib/utils"
|
"github.com/hdt3213/godis/lib/utils"
|
||||||
"github.com/hdt3213/godis/redis/reply"
|
"github.com/hdt3213/godis/redis/protocol"
|
||||||
"github.com/hdt3213/godis/redis/reply/asserts"
|
"github.com/hdt3213/godis/redis/protocol/asserts"
|
||||||
"strconv"
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
@@ -72,9 +72,9 @@ func TestGeoDist(t *testing.T) {
|
|||||||
"15.087269", "37.502669", pos2,
|
"15.087269", "37.502669", pos2,
|
||||||
))
|
))
|
||||||
result := execGeoDist(testDB, utils.ToCmdLine(key, pos1, pos2, "km"))
|
result := execGeoDist(testDB, utils.ToCmdLine(key, pos1, pos2, "km"))
|
||||||
bulkReply, ok := result.(*reply.BulkReply)
|
bulkReply, ok := result.(*protocol.BulkReply)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Error(fmt.Sprintf("expected bulk reply, actually %s", result.ToBytes()))
|
t.Error(fmt.Sprintf("expected bulk protocol, actually %s", result.ToBytes()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
dist, err := strconv.ParseFloat(string(bulkReply.Arg), 10)
|
dist, err := strconv.ParseFloat(string(bulkReply.Arg), 10)
|
||||||
@@ -87,9 +87,9 @@ func TestGeoDist(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
result = execGeoDist(testDB, utils.ToCmdLine(key, pos1, pos2, "m"))
|
result = execGeoDist(testDB, utils.ToCmdLine(key, pos1, pos2, "m"))
|
||||||
bulkReply, ok = result.(*reply.BulkReply)
|
bulkReply, ok = result.(*protocol.BulkReply)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Error(fmt.Sprintf("expected bulk reply, actually %s", result.ToBytes()))
|
t.Error(fmt.Sprintf("expected bulk protocol, actually %s", result.ToBytes()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
dist, err = strconv.ParseFloat(string(bulkReply.Arg), 10)
|
dist, err = strconv.ParseFloat(string(bulkReply.Arg), 10)
|
||||||
|
@@ -5,24 +5,24 @@ import (
|
|||||||
"github.com/hdt3213/godis/interface/database"
|
"github.com/hdt3213/godis/interface/database"
|
||||||
"github.com/hdt3213/godis/interface/redis"
|
"github.com/hdt3213/godis/interface/redis"
|
||||||
"github.com/hdt3213/godis/lib/utils"
|
"github.com/hdt3213/godis/lib/utils"
|
||||||
"github.com/hdt3213/godis/redis/reply"
|
"github.com/hdt3213/godis/redis/protocol"
|
||||||
"github.com/shopspring/decimal"
|
"github.com/shopspring/decimal"
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (db *DB) getAsDict(key string) (Dict.Dict, reply.ErrorReply) {
|
func (db *DB) getAsDict(key string) (Dict.Dict, protocol.ErrorReply) {
|
||||||
entity, exists := db.GetEntity(key)
|
entity, exists := db.GetEntity(key)
|
||||||
if !exists {
|
if !exists {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
dict, ok := entity.Data.(Dict.Dict)
|
dict, ok := entity.Data.(Dict.Dict)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, &reply.WrongTypeErrReply{}
|
return nil, &protocol.WrongTypeErrReply{}
|
||||||
}
|
}
|
||||||
return dict, nil
|
return dict, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) getOrInitDict(key string) (dict Dict.Dict, inited bool, errReply reply.ErrorReply) {
|
func (db *DB) getOrInitDict(key string) (dict Dict.Dict, inited bool, errReply protocol.ErrorReply) {
|
||||||
dict, errReply = db.getAsDict(key)
|
dict, errReply = db.getAsDict(key)
|
||||||
if errReply != nil {
|
if errReply != nil {
|
||||||
return nil, false, errReply
|
return nil, false, errReply
|
||||||
@@ -53,7 +53,7 @@ func execHSet(db *DB, args [][]byte) redis.Reply {
|
|||||||
|
|
||||||
result := dict.Put(field, value)
|
result := dict.Put(field, value)
|
||||||
db.addAof(utils.ToCmdLine3("hset", args...))
|
db.addAof(utils.ToCmdLine3("hset", args...))
|
||||||
return reply.MakeIntReply(int64(result))
|
return protocol.MakeIntReply(int64(result))
|
||||||
}
|
}
|
||||||
|
|
||||||
func undoHSet(db *DB, args [][]byte) []CmdLine {
|
func undoHSet(db *DB, args [][]byte) []CmdLine {
|
||||||
@@ -79,7 +79,7 @@ func execHSetNX(db *DB, args [][]byte) redis.Reply {
|
|||||||
db.addAof(utils.ToCmdLine3("hsetnx", args...))
|
db.addAof(utils.ToCmdLine3("hsetnx", args...))
|
||||||
|
|
||||||
}
|
}
|
||||||
return reply.MakeIntReply(int64(result))
|
return protocol.MakeIntReply(int64(result))
|
||||||
}
|
}
|
||||||
|
|
||||||
// execHGet gets field value of hash table
|
// execHGet gets field value of hash table
|
||||||
@@ -94,15 +94,15 @@ func execHGet(db *DB, args [][]byte) redis.Reply {
|
|||||||
return errReply
|
return errReply
|
||||||
}
|
}
|
||||||
if dict == nil {
|
if dict == nil {
|
||||||
return &reply.NullBulkReply{}
|
return &protocol.NullBulkReply{}
|
||||||
}
|
}
|
||||||
|
|
||||||
raw, exists := dict.Get(field)
|
raw, exists := dict.Get(field)
|
||||||
if !exists {
|
if !exists {
|
||||||
return &reply.NullBulkReply{}
|
return &protocol.NullBulkReply{}
|
||||||
}
|
}
|
||||||
value, _ := raw.([]byte)
|
value, _ := raw.([]byte)
|
||||||
return reply.MakeBulkReply(value)
|
return protocol.MakeBulkReply(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
// execHExists checks if a hash field exists
|
// execHExists checks if a hash field exists
|
||||||
@@ -117,14 +117,14 @@ func execHExists(db *DB, args [][]byte) redis.Reply {
|
|||||||
return errReply
|
return errReply
|
||||||
}
|
}
|
||||||
if dict == nil {
|
if dict == nil {
|
||||||
return reply.MakeIntReply(0)
|
return protocol.MakeIntReply(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, exists := dict.Get(field)
|
_, exists := dict.Get(field)
|
||||||
if exists {
|
if exists {
|
||||||
return reply.MakeIntReply(1)
|
return protocol.MakeIntReply(1)
|
||||||
}
|
}
|
||||||
return reply.MakeIntReply(0)
|
return protocol.MakeIntReply(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// execHDel deletes a hash field
|
// execHDel deletes a hash field
|
||||||
@@ -143,7 +143,7 @@ func execHDel(db *DB, args [][]byte) redis.Reply {
|
|||||||
return errReply
|
return errReply
|
||||||
}
|
}
|
||||||
if dict == nil {
|
if dict == nil {
|
||||||
return reply.MakeIntReply(0)
|
return protocol.MakeIntReply(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
deleted := 0
|
deleted := 0
|
||||||
@@ -158,7 +158,7 @@ func execHDel(db *DB, args [][]byte) redis.Reply {
|
|||||||
db.addAof(utils.ToCmdLine3("hdel", args...))
|
db.addAof(utils.ToCmdLine3("hdel", args...))
|
||||||
}
|
}
|
||||||
|
|
||||||
return reply.MakeIntReply(int64(deleted))
|
return protocol.MakeIntReply(int64(deleted))
|
||||||
}
|
}
|
||||||
|
|
||||||
func undoHDel(db *DB, args [][]byte) []CmdLine {
|
func undoHDel(db *DB, args [][]byte) []CmdLine {
|
||||||
@@ -181,16 +181,16 @@ func execHLen(db *DB, args [][]byte) redis.Reply {
|
|||||||
return errReply
|
return errReply
|
||||||
}
|
}
|
||||||
if dict == nil {
|
if dict == nil {
|
||||||
return reply.MakeIntReply(0)
|
return protocol.MakeIntReply(0)
|
||||||
}
|
}
|
||||||
return reply.MakeIntReply(int64(dict.Len()))
|
return protocol.MakeIntReply(int64(dict.Len()))
|
||||||
}
|
}
|
||||||
|
|
||||||
// execHMSet sets multi fields in hash table
|
// execHMSet sets multi fields in hash table
|
||||||
func execHMSet(db *DB, args [][]byte) redis.Reply {
|
func execHMSet(db *DB, args [][]byte) redis.Reply {
|
||||||
// parse args
|
// parse args
|
||||||
if len(args)%2 != 1 {
|
if len(args)%2 != 1 {
|
||||||
return reply.MakeSyntaxErrReply()
|
return protocol.MakeSyntaxErrReply()
|
||||||
}
|
}
|
||||||
key := string(args[0])
|
key := string(args[0])
|
||||||
size := (len(args) - 1) / 2
|
size := (len(args) - 1) / 2
|
||||||
@@ -213,7 +213,7 @@ func execHMSet(db *DB, args [][]byte) redis.Reply {
|
|||||||
dict.Put(field, value)
|
dict.Put(field, value)
|
||||||
}
|
}
|
||||||
db.addAof(utils.ToCmdLine3("hmset", args...))
|
db.addAof(utils.ToCmdLine3("hmset", args...))
|
||||||
return &reply.OkReply{}
|
return &protocol.OkReply{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func undoHMSet(db *DB, args [][]byte) []CmdLine {
|
func undoHMSet(db *DB, args [][]byte) []CmdLine {
|
||||||
@@ -242,7 +242,7 @@ func execHMGet(db *DB, args [][]byte) redis.Reply {
|
|||||||
return errReply
|
return errReply
|
||||||
}
|
}
|
||||||
if dict == nil {
|
if dict == nil {
|
||||||
return reply.MakeMultiBulkReply(result)
|
return protocol.MakeMultiBulkReply(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, field := range fields {
|
for i, field := range fields {
|
||||||
@@ -254,7 +254,7 @@ func execHMGet(db *DB, args [][]byte) redis.Reply {
|
|||||||
result[i] = bytes
|
result[i] = bytes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return reply.MakeMultiBulkReply(result)
|
return protocol.MakeMultiBulkReply(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
// execHKeys gets all field names in hash table
|
// execHKeys gets all field names in hash table
|
||||||
@@ -266,7 +266,7 @@ func execHKeys(db *DB, args [][]byte) redis.Reply {
|
|||||||
return errReply
|
return errReply
|
||||||
}
|
}
|
||||||
if dict == nil {
|
if dict == nil {
|
||||||
return &reply.EmptyMultiBulkReply{}
|
return &protocol.EmptyMultiBulkReply{}
|
||||||
}
|
}
|
||||||
|
|
||||||
fields := make([][]byte, dict.Len())
|
fields := make([][]byte, dict.Len())
|
||||||
@@ -276,7 +276,7 @@ func execHKeys(db *DB, args [][]byte) redis.Reply {
|
|||||||
i++
|
i++
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
return reply.MakeMultiBulkReply(fields[:i])
|
return protocol.MakeMultiBulkReply(fields[:i])
|
||||||
}
|
}
|
||||||
|
|
||||||
// execHVals gets all field value in hash table
|
// execHVals gets all field value in hash table
|
||||||
@@ -289,7 +289,7 @@ func execHVals(db *DB, args [][]byte) redis.Reply {
|
|||||||
return errReply
|
return errReply
|
||||||
}
|
}
|
||||||
if dict == nil {
|
if dict == nil {
|
||||||
return &reply.EmptyMultiBulkReply{}
|
return &protocol.EmptyMultiBulkReply{}
|
||||||
}
|
}
|
||||||
|
|
||||||
values := make([][]byte, dict.Len())
|
values := make([][]byte, dict.Len())
|
||||||
@@ -299,7 +299,7 @@ func execHVals(db *DB, args [][]byte) redis.Reply {
|
|||||||
i++
|
i++
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
return reply.MakeMultiBulkReply(values[:i])
|
return protocol.MakeMultiBulkReply(values[:i])
|
||||||
}
|
}
|
||||||
|
|
||||||
// execHGetAll gets all key-value entries in hash table
|
// execHGetAll gets all key-value entries in hash table
|
||||||
@@ -312,7 +312,7 @@ func execHGetAll(db *DB, args [][]byte) redis.Reply {
|
|||||||
return errReply
|
return errReply
|
||||||
}
|
}
|
||||||
if dict == nil {
|
if dict == nil {
|
||||||
return &reply.EmptyMultiBulkReply{}
|
return &protocol.EmptyMultiBulkReply{}
|
||||||
}
|
}
|
||||||
|
|
||||||
size := dict.Len()
|
size := dict.Len()
|
||||||
@@ -325,7 +325,7 @@ func execHGetAll(db *DB, args [][]byte) redis.Reply {
|
|||||||
i++
|
i++
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
return reply.MakeMultiBulkReply(result[:i])
|
return protocol.MakeMultiBulkReply(result[:i])
|
||||||
}
|
}
|
||||||
|
|
||||||
// execHIncrBy increments the integer value of a hash field by the given number
|
// execHIncrBy increments the integer value of a hash field by the given number
|
||||||
@@ -335,7 +335,7 @@ func execHIncrBy(db *DB, args [][]byte) redis.Reply {
|
|||||||
rawDelta := string(args[2])
|
rawDelta := string(args[2])
|
||||||
delta, err := strconv.ParseInt(rawDelta, 10, 64)
|
delta, err := strconv.ParseInt(rawDelta, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reply.MakeErrReply("ERR value is not an integer or out of range")
|
return protocol.MakeErrReply("ERR value is not an integer or out of range")
|
||||||
}
|
}
|
||||||
|
|
||||||
dict, _, errReply := db.getOrInitDict(key)
|
dict, _, errReply := db.getOrInitDict(key)
|
||||||
@@ -347,17 +347,17 @@ func execHIncrBy(db *DB, args [][]byte) redis.Reply {
|
|||||||
if !exists {
|
if !exists {
|
||||||
dict.Put(field, args[2])
|
dict.Put(field, args[2])
|
||||||
db.addAof(utils.ToCmdLine3("hincrby", args...))
|
db.addAof(utils.ToCmdLine3("hincrby", args...))
|
||||||
return reply.MakeBulkReply(args[2])
|
return protocol.MakeBulkReply(args[2])
|
||||||
}
|
}
|
||||||
val, err := strconv.ParseInt(string(value.([]byte)), 10, 64)
|
val, err := strconv.ParseInt(string(value.([]byte)), 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reply.MakeErrReply("ERR hash value is not an integer")
|
return protocol.MakeErrReply("ERR hash value is not an integer")
|
||||||
}
|
}
|
||||||
val += delta
|
val += delta
|
||||||
bytes := []byte(strconv.FormatInt(val, 10))
|
bytes := []byte(strconv.FormatInt(val, 10))
|
||||||
dict.Put(field, bytes)
|
dict.Put(field, bytes)
|
||||||
db.addAof(utils.ToCmdLine3("hincrby", args...))
|
db.addAof(utils.ToCmdLine3("hincrby", args...))
|
||||||
return reply.MakeBulkReply(bytes)
|
return protocol.MakeBulkReply(bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
func undoHIncr(db *DB, args [][]byte) []CmdLine {
|
func undoHIncr(db *DB, args [][]byte) []CmdLine {
|
||||||
@@ -373,7 +373,7 @@ func execHIncrByFloat(db *DB, args [][]byte) redis.Reply {
|
|||||||
rawDelta := string(args[2])
|
rawDelta := string(args[2])
|
||||||
delta, err := decimal.NewFromString(rawDelta)
|
delta, err := decimal.NewFromString(rawDelta)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reply.MakeErrReply("ERR value is not a valid float")
|
return protocol.MakeErrReply("ERR value is not a valid float")
|
||||||
}
|
}
|
||||||
|
|
||||||
// get or init entity
|
// get or init entity
|
||||||
@@ -385,17 +385,17 @@ func execHIncrByFloat(db *DB, args [][]byte) redis.Reply {
|
|||||||
value, exists := dict.Get(field)
|
value, exists := dict.Get(field)
|
||||||
if !exists {
|
if !exists {
|
||||||
dict.Put(field, args[2])
|
dict.Put(field, args[2])
|
||||||
return reply.MakeBulkReply(args[2])
|
return protocol.MakeBulkReply(args[2])
|
||||||
}
|
}
|
||||||
val, err := decimal.NewFromString(string(value.([]byte)))
|
val, err := decimal.NewFromString(string(value.([]byte)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reply.MakeErrReply("ERR hash value is not a float")
|
return protocol.MakeErrReply("ERR hash value is not a float")
|
||||||
}
|
}
|
||||||
result := val.Add(delta)
|
result := val.Add(delta)
|
||||||
resultBytes := []byte(result.String())
|
resultBytes := []byte(result.String())
|
||||||
dict.Put(field, resultBytes)
|
dict.Put(field, resultBytes)
|
||||||
db.addAof(utils.ToCmdLine3("hincrbyfloat", args...))
|
db.addAof(utils.ToCmdLine3("hincrbyfloat", args...))
|
||||||
return reply.MakeBulkReply(resultBytes)
|
return protocol.MakeBulkReply(resultBytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@@ -3,8 +3,8 @@ package database
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/hdt3213/godis/lib/utils"
|
"github.com/hdt3213/godis/lib/utils"
|
||||||
"github.com/hdt3213/godis/redis/reply"
|
"github.com/hdt3213/godis/redis/protocol"
|
||||||
"github.com/hdt3213/godis/redis/reply/asserts"
|
"github.com/hdt3213/godis/redis/protocol/asserts"
|
||||||
"strconv"
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
@@ -21,7 +21,7 @@ func TestHSet(t *testing.T) {
|
|||||||
field := strconv.Itoa(i)
|
field := strconv.Itoa(i)
|
||||||
values[field] = []byte(value)
|
values[field] = []byte(value)
|
||||||
result := testDB.Exec(nil, utils.ToCmdLine("hset", key, field, value))
|
result := testDB.Exec(nil, utils.ToCmdLine("hset", key, field, value))
|
||||||
if intResult, _ := result.(*reply.IntReply); intResult.Code != int64(1) {
|
if intResult, _ := result.(*protocol.IntReply); intResult.Code != int64(1) {
|
||||||
t.Error(fmt.Sprintf("expected %d, actually %d", 1, intResult.Code))
|
t.Error(fmt.Sprintf("expected %d, actually %d", 1, intResult.Code))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -29,19 +29,19 @@ func TestHSet(t *testing.T) {
|
|||||||
// test hget and hexists
|
// test hget and hexists
|
||||||
for field, v := range values {
|
for field, v := range values {
|
||||||
actual := testDB.Exec(nil, utils.ToCmdLine("hget", key, field))
|
actual := testDB.Exec(nil, utils.ToCmdLine("hget", key, field))
|
||||||
expected := reply.MakeBulkReply(v)
|
expected := protocol.MakeBulkReply(v)
|
||||||
if !utils.BytesEquals(actual.ToBytes(), expected.ToBytes()) {
|
if !utils.BytesEquals(actual.ToBytes(), expected.ToBytes()) {
|
||||||
t.Error(fmt.Sprintf("expected %s, actually %s", string(expected.ToBytes()), string(actual.ToBytes())))
|
t.Error(fmt.Sprintf("expected %s, actually %s", string(expected.ToBytes()), string(actual.ToBytes())))
|
||||||
}
|
}
|
||||||
actual = testDB.Exec(nil, utils.ToCmdLine("hexists", key, field))
|
actual = testDB.Exec(nil, utils.ToCmdLine("hexists", key, field))
|
||||||
if intResult, _ := actual.(*reply.IntReply); intResult.Code != int64(1) {
|
if intResult, _ := actual.(*protocol.IntReply); intResult.Code != int64(1) {
|
||||||
t.Error(fmt.Sprintf("expected %d, actually %d", 1, intResult.Code))
|
t.Error(fmt.Sprintf("expected %d, actually %d", 1, intResult.Code))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// test hlen
|
// test hlen
|
||||||
actual := testDB.Exec(nil, utils.ToCmdLine("hlen", key))
|
actual := testDB.Exec(nil, utils.ToCmdLine("hlen", key))
|
||||||
if intResult, _ := actual.(*reply.IntReply); intResult.Code != int64(len(values)) {
|
if intResult, _ := actual.(*protocol.IntReply); intResult.Code != int64(len(values)) {
|
||||||
t.Error(fmt.Sprintf("expected %d, actually %d", len(values), intResult.Code))
|
t.Error(fmt.Sprintf("expected %d, actually %d", len(values), intResult.Code))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -64,12 +64,12 @@ func TestHDel(t *testing.T) {
|
|||||||
args := []string{key}
|
args := []string{key}
|
||||||
args = append(args, fields...)
|
args = append(args, fields...)
|
||||||
actual := testDB.Exec(nil, utils.ToCmdLine2("hdel", args...))
|
actual := testDB.Exec(nil, utils.ToCmdLine2("hdel", args...))
|
||||||
if intResult, _ := actual.(*reply.IntReply); intResult.Code != int64(len(fields)) {
|
if intResult, _ := actual.(*protocol.IntReply); intResult.Code != int64(len(fields)) {
|
||||||
t.Error(fmt.Sprintf("expected %d, actually %d", len(fields), intResult.Code))
|
t.Error(fmt.Sprintf("expected %d, actually %d", len(fields), intResult.Code))
|
||||||
}
|
}
|
||||||
|
|
||||||
actual = testDB.Exec(nil, utils.ToCmdLine("hlen", key))
|
actual = testDB.Exec(nil, utils.ToCmdLine("hlen", key))
|
||||||
if intResult, _ := actual.(*reply.IntReply); intResult.Code != int64(0) {
|
if intResult, _ := actual.(*protocol.IntReply); intResult.Code != int64(0) {
|
||||||
t.Error(fmt.Sprintf("expected %d, actually %d", 0, intResult.Code))
|
t.Error(fmt.Sprintf("expected %d, actually %d", 0, intResult.Code))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -89,7 +89,7 @@ func TestHMSet(t *testing.T) {
|
|||||||
setArgs = append(setArgs, fields[i], values[i])
|
setArgs = append(setArgs, fields[i], values[i])
|
||||||
}
|
}
|
||||||
result := testDB.Exec(nil, utils.ToCmdLine2("hmset", setArgs...))
|
result := testDB.Exec(nil, utils.ToCmdLine2("hmset", setArgs...))
|
||||||
if _, ok := result.(*reply.OkReply); !ok {
|
if _, ok := result.(*protocol.OkReply); !ok {
|
||||||
t.Error(fmt.Sprintf("expected ok, actually %s", string(result.ToBytes())))
|
t.Error(fmt.Sprintf("expected ok, actually %s", string(result.ToBytes())))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -97,7 +97,7 @@ func TestHMSet(t *testing.T) {
|
|||||||
getArgs := []string{key}
|
getArgs := []string{key}
|
||||||
getArgs = append(getArgs, fields...)
|
getArgs = append(getArgs, fields...)
|
||||||
actual := testDB.Exec(nil, utils.ToCmdLine2("hmget", getArgs...))
|
actual := testDB.Exec(nil, utils.ToCmdLine2("hmget", getArgs...))
|
||||||
expected := reply.MakeMultiBulkReply(utils.ToCmdLine(values...))
|
expected := protocol.MakeMultiBulkReply(utils.ToCmdLine(values...))
|
||||||
if !utils.BytesEquals(actual.ToBytes(), expected.ToBytes()) {
|
if !utils.BytesEquals(actual.ToBytes(), expected.ToBytes()) {
|
||||||
t.Error(fmt.Sprintf("expected %s, actually %s", string(expected.ToBytes()), string(actual.ToBytes())))
|
t.Error(fmt.Sprintf("expected %s, actually %s", string(expected.ToBytes()), string(actual.ToBytes())))
|
||||||
}
|
}
|
||||||
@@ -122,7 +122,7 @@ func TestHGetAll(t *testing.T) {
|
|||||||
|
|
||||||
// test HGetAll
|
// test HGetAll
|
||||||
result := testDB.Exec(nil, utils.ToCmdLine("hgetall", key))
|
result := testDB.Exec(nil, utils.ToCmdLine("hgetall", key))
|
||||||
multiBulk, ok := result.(*reply.MultiBulkReply)
|
multiBulk, ok := result.(*protocol.MultiBulkReply)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Error(fmt.Sprintf("expected MultiBulkReply, actually %s", string(result.ToBytes())))
|
t.Error(fmt.Sprintf("expected MultiBulkReply, actually %s", string(result.ToBytes())))
|
||||||
}
|
}
|
||||||
@@ -144,7 +144,7 @@ func TestHGetAll(t *testing.T) {
|
|||||||
|
|
||||||
// test HKeys
|
// test HKeys
|
||||||
result = testDB.Exec(nil, utils.ToCmdLine("hkeys", key))
|
result = testDB.Exec(nil, utils.ToCmdLine("hkeys", key))
|
||||||
multiBulk, ok = result.(*reply.MultiBulkReply)
|
multiBulk, ok = result.(*protocol.MultiBulkReply)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Error(fmt.Sprintf("expected MultiBulkReply, actually %s", string(result.ToBytes())))
|
t.Error(fmt.Sprintf("expected MultiBulkReply, actually %s", string(result.ToBytes())))
|
||||||
}
|
}
|
||||||
@@ -160,7 +160,7 @@ func TestHGetAll(t *testing.T) {
|
|||||||
|
|
||||||
// test HVals
|
// test HVals
|
||||||
result = testDB.Exec(nil, utils.ToCmdLine("hvals", key))
|
result = testDB.Exec(nil, utils.ToCmdLine("hvals", key))
|
||||||
multiBulk, ok = result.(*reply.MultiBulkReply)
|
multiBulk, ok = result.(*protocol.MultiBulkReply)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Error(fmt.Sprintf("expected MultiBulkReply, actually %s", string(result.ToBytes())))
|
t.Error(fmt.Sprintf("expected MultiBulkReply, actually %s", string(result.ToBytes())))
|
||||||
}
|
}
|
||||||
@@ -181,20 +181,20 @@ func TestHIncrBy(t *testing.T) {
|
|||||||
|
|
||||||
key := utils.RandString(10)
|
key := utils.RandString(10)
|
||||||
result := testDB.Exec(nil, utils.ToCmdLine("hincrby", key, "a", "1"))
|
result := testDB.Exec(nil, utils.ToCmdLine("hincrby", key, "a", "1"))
|
||||||
if bulkResult, _ := result.(*reply.BulkReply); string(bulkResult.Arg) != "1" {
|
if bulkResult, _ := result.(*protocol.BulkReply); string(bulkResult.Arg) != "1" {
|
||||||
t.Error(fmt.Sprintf("expected %s, actually %s", "1", string(bulkResult.Arg)))
|
t.Error(fmt.Sprintf("expected %s, actually %s", "1", string(bulkResult.Arg)))
|
||||||
}
|
}
|
||||||
result = testDB.Exec(nil, utils.ToCmdLine("hincrby", key, "a", "1"))
|
result = testDB.Exec(nil, utils.ToCmdLine("hincrby", key, "a", "1"))
|
||||||
if bulkResult, _ := result.(*reply.BulkReply); string(bulkResult.Arg) != "2" {
|
if bulkResult, _ := result.(*protocol.BulkReply); string(bulkResult.Arg) != "2" {
|
||||||
t.Error(fmt.Sprintf("expected %s, actually %s", "2", string(bulkResult.Arg)))
|
t.Error(fmt.Sprintf("expected %s, actually %s", "2", string(bulkResult.Arg)))
|
||||||
}
|
}
|
||||||
|
|
||||||
result = testDB.Exec(nil, utils.ToCmdLine("hincrbyfloat", key, "b", "1.2"))
|
result = testDB.Exec(nil, utils.ToCmdLine("hincrbyfloat", key, "b", "1.2"))
|
||||||
if bulkResult, _ := result.(*reply.BulkReply); string(bulkResult.Arg) != "1.2" {
|
if bulkResult, _ := result.(*protocol.BulkReply); string(bulkResult.Arg) != "1.2" {
|
||||||
t.Error(fmt.Sprintf("expected %s, actually %s", "1.2", string(bulkResult.Arg)))
|
t.Error(fmt.Sprintf("expected %s, actually %s", "1.2", string(bulkResult.Arg)))
|
||||||
}
|
}
|
||||||
result = testDB.Exec(nil, utils.ToCmdLine("hincrbyfloat", key, "b", "1.2"))
|
result = testDB.Exec(nil, utils.ToCmdLine("hincrbyfloat", key, "b", "1.2"))
|
||||||
if bulkResult, _ := result.(*reply.BulkReply); string(bulkResult.Arg) != "2.4" {
|
if bulkResult, _ := result.(*protocol.BulkReply); string(bulkResult.Arg) != "2.4" {
|
||||||
t.Error(fmt.Sprintf("expected %s, actually %s", "2.4", string(bulkResult.Arg)))
|
t.Error(fmt.Sprintf("expected %s, actually %s", "2.4", string(bulkResult.Arg)))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -9,7 +9,7 @@ import (
|
|||||||
"github.com/hdt3213/godis/interface/redis"
|
"github.com/hdt3213/godis/interface/redis"
|
||||||
"github.com/hdt3213/godis/lib/utils"
|
"github.com/hdt3213/godis/lib/utils"
|
||||||
"github.com/hdt3213/godis/lib/wildcard"
|
"github.com/hdt3213/godis/lib/wildcard"
|
||||||
"github.com/hdt3213/godis/redis/reply"
|
"github.com/hdt3213/godis/redis/protocol"
|
||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
@@ -25,7 +25,7 @@ func execDel(db *DB, args [][]byte) redis.Reply {
|
|||||||
if deleted > 0 {
|
if deleted > 0 {
|
||||||
db.addAof(utils.ToCmdLine3("del", args...))
|
db.addAof(utils.ToCmdLine3("del", args...))
|
||||||
}
|
}
|
||||||
return reply.MakeIntReply(int64(deleted))
|
return protocol.MakeIntReply(int64(deleted))
|
||||||
}
|
}
|
||||||
|
|
||||||
func undoDel(db *DB, args [][]byte) []CmdLine {
|
func undoDel(db *DB, args [][]byte) []CmdLine {
|
||||||
@@ -46,7 +46,7 @@ func execExists(db *DB, args [][]byte) redis.Reply {
|
|||||||
result++
|
result++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return reply.MakeIntReply(result)
|
return protocol.MakeIntReply(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
// execExistIn returns existing key in given keys
|
// execExistIn returns existing key in given keys
|
||||||
@@ -62,16 +62,16 @@ func execExistIn(db *DB, args [][]byte) redis.Reply {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if len(result) == 0 {
|
if len(result) == 0 {
|
||||||
return reply.MakeEmptyMultiBulkReply()
|
return protocol.MakeEmptyMultiBulkReply()
|
||||||
}
|
}
|
||||||
return reply.MakeMultiBulkReply(result)
|
return protocol.MakeMultiBulkReply(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
// execFlushDB removes all data in current db
|
// execFlushDB removes all data in current db
|
||||||
func execFlushDB(db *DB, args [][]byte) redis.Reply {
|
func execFlushDB(db *DB, args [][]byte) redis.Reply {
|
||||||
db.Flush()
|
db.Flush()
|
||||||
db.addAof(utils.ToCmdLine3("flushdb", args...))
|
db.addAof(utils.ToCmdLine3("flushdb", args...))
|
||||||
return &reply.OkReply{}
|
return &protocol.OkReply{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// execType returns the type of entity, including: string, list, hash, set and zset
|
// execType returns the type of entity, including: string, list, hash, set and zset
|
||||||
@@ -79,21 +79,21 @@ func execType(db *DB, args [][]byte) redis.Reply {
|
|||||||
key := string(args[0])
|
key := string(args[0])
|
||||||
entity, exists := db.GetEntity(key)
|
entity, exists := db.GetEntity(key)
|
||||||
if !exists {
|
if !exists {
|
||||||
return reply.MakeStatusReply("none")
|
return protocol.MakeStatusReply("none")
|
||||||
}
|
}
|
||||||
switch entity.Data.(type) {
|
switch entity.Data.(type) {
|
||||||
case []byte:
|
case []byte:
|
||||||
return reply.MakeStatusReply("string")
|
return protocol.MakeStatusReply("string")
|
||||||
case *list.LinkedList:
|
case *list.LinkedList:
|
||||||
return reply.MakeStatusReply("list")
|
return protocol.MakeStatusReply("list")
|
||||||
case dict.Dict:
|
case dict.Dict:
|
||||||
return reply.MakeStatusReply("hash")
|
return protocol.MakeStatusReply("hash")
|
||||||
case *set.Set:
|
case *set.Set:
|
||||||
return reply.MakeStatusReply("set")
|
return protocol.MakeStatusReply("set")
|
||||||
case *sortedset.SortedSet:
|
case *sortedset.SortedSet:
|
||||||
return reply.MakeStatusReply("zset")
|
return protocol.MakeStatusReply("zset")
|
||||||
}
|
}
|
||||||
return &reply.UnknownErrReply{}
|
return &protocol.UnknownErrReply{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func prepareRename(args [][]byte) ([]string, []string) {
|
func prepareRename(args [][]byte) ([]string, []string) {
|
||||||
@@ -105,14 +105,14 @@ func prepareRename(args [][]byte) ([]string, []string) {
|
|||||||
// execRename a key
|
// execRename a key
|
||||||
func execRename(db *DB, args [][]byte) redis.Reply {
|
func execRename(db *DB, args [][]byte) redis.Reply {
|
||||||
if len(args) != 2 {
|
if len(args) != 2 {
|
||||||
return reply.MakeErrReply("ERR wrong number of arguments for 'rename' command")
|
return protocol.MakeErrReply("ERR wrong number of arguments for 'rename' command")
|
||||||
}
|
}
|
||||||
src := string(args[0])
|
src := string(args[0])
|
||||||
dest := string(args[1])
|
dest := string(args[1])
|
||||||
|
|
||||||
entity, ok := db.GetEntity(src)
|
entity, ok := db.GetEntity(src)
|
||||||
if !ok {
|
if !ok {
|
||||||
return reply.MakeErrReply("no such key")
|
return protocol.MakeErrReply("no such key")
|
||||||
}
|
}
|
||||||
rawTTL, hasTTL := db.ttlMap.Get(src)
|
rawTTL, hasTTL := db.ttlMap.Get(src)
|
||||||
db.PutEntity(dest, entity)
|
db.PutEntity(dest, entity)
|
||||||
@@ -124,7 +124,7 @@ func execRename(db *DB, args [][]byte) redis.Reply {
|
|||||||
db.Expire(dest, expireTime)
|
db.Expire(dest, expireTime)
|
||||||
}
|
}
|
||||||
db.addAof(utils.ToCmdLine3("rename", args...))
|
db.addAof(utils.ToCmdLine3("rename", args...))
|
||||||
return &reply.OkReply{}
|
return &protocol.OkReply{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func undoRename(db *DB, args [][]byte) []CmdLine {
|
func undoRename(db *DB, args [][]byte) []CmdLine {
|
||||||
@@ -140,12 +140,12 @@ func execRenameNx(db *DB, args [][]byte) redis.Reply {
|
|||||||
|
|
||||||
_, ok := db.GetEntity(dest)
|
_, ok := db.GetEntity(dest)
|
||||||
if ok {
|
if ok {
|
||||||
return reply.MakeIntReply(0)
|
return protocol.MakeIntReply(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
entity, ok := db.GetEntity(src)
|
entity, ok := db.GetEntity(src)
|
||||||
if !ok {
|
if !ok {
|
||||||
return reply.MakeErrReply("no such key")
|
return protocol.MakeErrReply("no such key")
|
||||||
}
|
}
|
||||||
rawTTL, hasTTL := db.ttlMap.Get(src)
|
rawTTL, hasTTL := db.ttlMap.Get(src)
|
||||||
db.Removes(src, dest) // clean src and dest with their ttl
|
db.Removes(src, dest) // clean src and dest with their ttl
|
||||||
@@ -157,7 +157,7 @@ func execRenameNx(db *DB, args [][]byte) redis.Reply {
|
|||||||
db.Expire(dest, expireTime)
|
db.Expire(dest, expireTime)
|
||||||
}
|
}
|
||||||
db.addAof(utils.ToCmdLine3("renamenx", args...))
|
db.addAof(utils.ToCmdLine3("renamenx", args...))
|
||||||
return reply.MakeIntReply(1)
|
return protocol.MakeIntReply(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// execExpire sets a key's time to live in seconds
|
// execExpire sets a key's time to live in seconds
|
||||||
@@ -166,19 +166,19 @@ func execExpire(db *DB, args [][]byte) redis.Reply {
|
|||||||
|
|
||||||
ttlArg, err := strconv.ParseInt(string(args[1]), 10, 64)
|
ttlArg, err := strconv.ParseInt(string(args[1]), 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reply.MakeErrReply("ERR value is not an integer or out of range")
|
return protocol.MakeErrReply("ERR value is not an integer or out of range")
|
||||||
}
|
}
|
||||||
ttl := time.Duration(ttlArg) * time.Second
|
ttl := time.Duration(ttlArg) * time.Second
|
||||||
|
|
||||||
_, exists := db.GetEntity(key)
|
_, exists := db.GetEntity(key)
|
||||||
if !exists {
|
if !exists {
|
||||||
return reply.MakeIntReply(0)
|
return protocol.MakeIntReply(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
expireAt := time.Now().Add(ttl)
|
expireAt := time.Now().Add(ttl)
|
||||||
db.Expire(key, expireAt)
|
db.Expire(key, expireAt)
|
||||||
db.addAof(aof.MakeExpireCmd(key, expireAt).Args)
|
db.addAof(aof.MakeExpireCmd(key, expireAt).Args)
|
||||||
return reply.MakeIntReply(1)
|
return protocol.MakeIntReply(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// execExpireAt sets a key's expiration in unix timestamp
|
// execExpireAt sets a key's expiration in unix timestamp
|
||||||
@@ -187,18 +187,18 @@ func execExpireAt(db *DB, args [][]byte) redis.Reply {
|
|||||||
|
|
||||||
raw, err := strconv.ParseInt(string(args[1]), 10, 64)
|
raw, err := strconv.ParseInt(string(args[1]), 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reply.MakeErrReply("ERR value is not an integer or out of range")
|
return protocol.MakeErrReply("ERR value is not an integer or out of range")
|
||||||
}
|
}
|
||||||
expireAt := time.Unix(raw, 0)
|
expireAt := time.Unix(raw, 0)
|
||||||
|
|
||||||
_, exists := db.GetEntity(key)
|
_, exists := db.GetEntity(key)
|
||||||
if !exists {
|
if !exists {
|
||||||
return reply.MakeIntReply(0)
|
return protocol.MakeIntReply(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
db.Expire(key, expireAt)
|
db.Expire(key, expireAt)
|
||||||
db.addAof(aof.MakeExpireCmd(key, expireAt).Args)
|
db.addAof(aof.MakeExpireCmd(key, expireAt).Args)
|
||||||
return reply.MakeIntReply(1)
|
return protocol.MakeIntReply(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// execPExpire sets a key's time to live in milliseconds
|
// execPExpire sets a key's time to live in milliseconds
|
||||||
@@ -207,19 +207,19 @@ func execPExpire(db *DB, args [][]byte) redis.Reply {
|
|||||||
|
|
||||||
ttlArg, err := strconv.ParseInt(string(args[1]), 10, 64)
|
ttlArg, err := strconv.ParseInt(string(args[1]), 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reply.MakeErrReply("ERR value is not an integer or out of range")
|
return protocol.MakeErrReply("ERR value is not an integer or out of range")
|
||||||
}
|
}
|
||||||
ttl := time.Duration(ttlArg) * time.Millisecond
|
ttl := time.Duration(ttlArg) * time.Millisecond
|
||||||
|
|
||||||
_, exists := db.GetEntity(key)
|
_, exists := db.GetEntity(key)
|
||||||
if !exists {
|
if !exists {
|
||||||
return reply.MakeIntReply(0)
|
return protocol.MakeIntReply(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
expireAt := time.Now().Add(ttl)
|
expireAt := time.Now().Add(ttl)
|
||||||
db.Expire(key, expireAt)
|
db.Expire(key, expireAt)
|
||||||
db.addAof(aof.MakeExpireCmd(key, expireAt).Args)
|
db.addAof(aof.MakeExpireCmd(key, expireAt).Args)
|
||||||
return reply.MakeIntReply(1)
|
return protocol.MakeIntReply(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// execPExpireAt sets a key's expiration in unix timestamp specified in milliseconds
|
// execPExpireAt sets a key's expiration in unix timestamp specified in milliseconds
|
||||||
@@ -228,19 +228,19 @@ func execPExpireAt(db *DB, args [][]byte) redis.Reply {
|
|||||||
|
|
||||||
raw, err := strconv.ParseInt(string(args[1]), 10, 64)
|
raw, err := strconv.ParseInt(string(args[1]), 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reply.MakeErrReply("ERR value is not an integer or out of range")
|
return protocol.MakeErrReply("ERR value is not an integer or out of range")
|
||||||
}
|
}
|
||||||
expireAt := time.Unix(0, raw*int64(time.Millisecond))
|
expireAt := time.Unix(0, raw*int64(time.Millisecond))
|
||||||
|
|
||||||
_, exists := db.GetEntity(key)
|
_, exists := db.GetEntity(key)
|
||||||
if !exists {
|
if !exists {
|
||||||
return reply.MakeIntReply(0)
|
return protocol.MakeIntReply(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
db.Expire(key, expireAt)
|
db.Expire(key, expireAt)
|
||||||
|
|
||||||
db.addAof(aof.MakeExpireCmd(key, expireAt).Args)
|
db.addAof(aof.MakeExpireCmd(key, expireAt).Args)
|
||||||
return reply.MakeIntReply(1)
|
return protocol.MakeIntReply(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// execTTL returns a key's time to live in seconds
|
// execTTL returns a key's time to live in seconds
|
||||||
@@ -248,16 +248,16 @@ func execTTL(db *DB, args [][]byte) redis.Reply {
|
|||||||
key := string(args[0])
|
key := string(args[0])
|
||||||
_, exists := db.GetEntity(key)
|
_, exists := db.GetEntity(key)
|
||||||
if !exists {
|
if !exists {
|
||||||
return reply.MakeIntReply(-2)
|
return protocol.MakeIntReply(-2)
|
||||||
}
|
}
|
||||||
|
|
||||||
raw, exists := db.ttlMap.Get(key)
|
raw, exists := db.ttlMap.Get(key)
|
||||||
if !exists {
|
if !exists {
|
||||||
return reply.MakeIntReply(-1)
|
return protocol.MakeIntReply(-1)
|
||||||
}
|
}
|
||||||
expireTime, _ := raw.(time.Time)
|
expireTime, _ := raw.(time.Time)
|
||||||
ttl := expireTime.Sub(time.Now())
|
ttl := expireTime.Sub(time.Now())
|
||||||
return reply.MakeIntReply(int64(ttl / time.Second))
|
return protocol.MakeIntReply(int64(ttl / time.Second))
|
||||||
}
|
}
|
||||||
|
|
||||||
// execPTTL returns a key's time to live in milliseconds
|
// execPTTL returns a key's time to live in milliseconds
|
||||||
@@ -265,16 +265,16 @@ func execPTTL(db *DB, args [][]byte) redis.Reply {
|
|||||||
key := string(args[0])
|
key := string(args[0])
|
||||||
_, exists := db.GetEntity(key)
|
_, exists := db.GetEntity(key)
|
||||||
if !exists {
|
if !exists {
|
||||||
return reply.MakeIntReply(-2)
|
return protocol.MakeIntReply(-2)
|
||||||
}
|
}
|
||||||
|
|
||||||
raw, exists := db.ttlMap.Get(key)
|
raw, exists := db.ttlMap.Get(key)
|
||||||
if !exists {
|
if !exists {
|
||||||
return reply.MakeIntReply(-1)
|
return protocol.MakeIntReply(-1)
|
||||||
}
|
}
|
||||||
expireTime, _ := raw.(time.Time)
|
expireTime, _ := raw.(time.Time)
|
||||||
ttl := expireTime.Sub(time.Now())
|
ttl := expireTime.Sub(time.Now())
|
||||||
return reply.MakeIntReply(int64(ttl / time.Millisecond))
|
return protocol.MakeIntReply(int64(ttl / time.Millisecond))
|
||||||
}
|
}
|
||||||
|
|
||||||
// execPersist removes expiration from a key
|
// execPersist removes expiration from a key
|
||||||
@@ -282,17 +282,17 @@ func execPersist(db *DB, args [][]byte) redis.Reply {
|
|||||||
key := string(args[0])
|
key := string(args[0])
|
||||||
_, exists := db.GetEntity(key)
|
_, exists := db.GetEntity(key)
|
||||||
if !exists {
|
if !exists {
|
||||||
return reply.MakeIntReply(0)
|
return protocol.MakeIntReply(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
_, exists = db.ttlMap.Get(key)
|
_, exists = db.ttlMap.Get(key)
|
||||||
if !exists {
|
if !exists {
|
||||||
return reply.MakeIntReply(0)
|
return protocol.MakeIntReply(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
db.Persist(key)
|
db.Persist(key)
|
||||||
db.addAof(utils.ToCmdLine3("persist", args...))
|
db.addAof(utils.ToCmdLine3("persist", args...))
|
||||||
return reply.MakeIntReply(1)
|
return protocol.MakeIntReply(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// execKeys returns all keys matching the given pattern
|
// execKeys returns all keys matching the given pattern
|
||||||
@@ -305,18 +305,18 @@ func execKeys(db *DB, args [][]byte) redis.Reply {
|
|||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
return reply.MakeMultiBulkReply(result)
|
return protocol.MakeMultiBulkReply(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
func toTTLCmd(db *DB, key string) *reply.MultiBulkReply {
|
func toTTLCmd(db *DB, key string) *protocol.MultiBulkReply {
|
||||||
raw, exists := db.ttlMap.Get(key)
|
raw, exists := db.ttlMap.Get(key)
|
||||||
if !exists {
|
if !exists {
|
||||||
// 无 TTL
|
// 无 TTL
|
||||||
return reply.MakeMultiBulkReply(utils.ToCmdLine("PERSIST", key))
|
return protocol.MakeMultiBulkReply(utils.ToCmdLine("PERSIST", key))
|
||||||
}
|
}
|
||||||
expireTime, _ := raw.(time.Time)
|
expireTime, _ := raw.(time.Time)
|
||||||
timestamp := strconv.FormatInt(expireTime.UnixNano()/1000/1000, 10)
|
timestamp := strconv.FormatInt(expireTime.UnixNano()/1000/1000, 10)
|
||||||
return reply.MakeMultiBulkReply(utils.ToCmdLine("PEXPIREAT", key, timestamp))
|
return protocol.MakeMultiBulkReply(utils.ToCmdLine("PEXPIREAT", key, timestamp))
|
||||||
}
|
}
|
||||||
|
|
||||||
func undoExpire(db *DB, args [][]byte) []CmdLine {
|
func undoExpire(db *DB, args [][]byte) []CmdLine {
|
||||||
|
@@ -3,8 +3,8 @@ package database
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/hdt3213/godis/lib/utils"
|
"github.com/hdt3213/godis/lib/utils"
|
||||||
"github.com/hdt3213/godis/redis/reply"
|
"github.com/hdt3213/godis/redis/protocol"
|
||||||
"github.com/hdt3213/godis/redis/reply/asserts"
|
"github.com/hdt3213/godis/redis/protocol/asserts"
|
||||||
"strconv"
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
@@ -73,7 +73,7 @@ func TestRename(t *testing.T) {
|
|||||||
newKey := key + utils.RandString(2)
|
newKey := key + utils.RandString(2)
|
||||||
testDB.Exec(nil, utils.ToCmdLine("set", key, value, "ex", "1000"))
|
testDB.Exec(nil, utils.ToCmdLine("set", key, value, "ex", "1000"))
|
||||||
result := testDB.Exec(nil, utils.ToCmdLine("rename", key, newKey))
|
result := testDB.Exec(nil, utils.ToCmdLine("rename", key, newKey))
|
||||||
if _, ok := result.(*reply.OkReply); !ok {
|
if _, ok := result.(*protocol.OkReply); !ok {
|
||||||
t.Error("expect ok")
|
t.Error("expect ok")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -83,9 +83,9 @@ func TestRename(t *testing.T) {
|
|||||||
asserts.AssertIntReply(t, result, 1)
|
asserts.AssertIntReply(t, result, 1)
|
||||||
// check ttl
|
// check ttl
|
||||||
result = testDB.Exec(nil, utils.ToCmdLine("ttl", newKey))
|
result = testDB.Exec(nil, utils.ToCmdLine("ttl", newKey))
|
||||||
intResult, ok := result.(*reply.IntReply)
|
intResult, ok := result.(*protocol.IntReply)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Error(fmt.Sprintf("expected int reply, actually %s", result.ToBytes()))
|
t.Error(fmt.Sprintf("expected int protocol, actually %s", result.ToBytes()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if intResult.Code <= 0 {
|
if intResult.Code <= 0 {
|
||||||
@@ -107,9 +107,9 @@ func TestRenameNx(t *testing.T) {
|
|||||||
result = testDB.Exec(nil, utils.ToCmdLine("exists", newKey))
|
result = testDB.Exec(nil, utils.ToCmdLine("exists", newKey))
|
||||||
asserts.AssertIntReply(t, result, 1)
|
asserts.AssertIntReply(t, result, 1)
|
||||||
result = testDB.Exec(nil, utils.ToCmdLine("ttl", newKey))
|
result = testDB.Exec(nil, utils.ToCmdLine("ttl", newKey))
|
||||||
intResult, ok := result.(*reply.IntReply)
|
intResult, ok := result.(*protocol.IntReply)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Error(fmt.Sprintf("expected int reply, actually %s", result.ToBytes()))
|
t.Error(fmt.Sprintf("expected int protocol, actually %s", result.ToBytes()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if intResult.Code <= 0 {
|
if intResult.Code <= 0 {
|
||||||
@@ -127,9 +127,9 @@ func TestTTL(t *testing.T) {
|
|||||||
result := testDB.Exec(nil, utils.ToCmdLine("expire", key, "1000"))
|
result := testDB.Exec(nil, utils.ToCmdLine("expire", key, "1000"))
|
||||||
asserts.AssertIntReply(t, result, 1)
|
asserts.AssertIntReply(t, result, 1)
|
||||||
result = testDB.Exec(nil, utils.ToCmdLine("ttl", key))
|
result = testDB.Exec(nil, utils.ToCmdLine("ttl", key))
|
||||||
intResult, ok := result.(*reply.IntReply)
|
intResult, ok := result.(*protocol.IntReply)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Error(fmt.Sprintf("expected int reply, actually %s", result.ToBytes()))
|
t.Error(fmt.Sprintf("expected int protocol, actually %s", result.ToBytes()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if intResult.Code <= 0 {
|
if intResult.Code <= 0 {
|
||||||
@@ -145,9 +145,9 @@ func TestTTL(t *testing.T) {
|
|||||||
result = testDB.Exec(nil, utils.ToCmdLine("PExpire", key, "1000000"))
|
result = testDB.Exec(nil, utils.ToCmdLine("PExpire", key, "1000000"))
|
||||||
asserts.AssertIntReply(t, result, 1)
|
asserts.AssertIntReply(t, result, 1)
|
||||||
result = testDB.Exec(nil, utils.ToCmdLine("PTTL", key))
|
result = testDB.Exec(nil, utils.ToCmdLine("PTTL", key))
|
||||||
intResult, ok = result.(*reply.IntReply)
|
intResult, ok = result.(*protocol.IntReply)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Error(fmt.Sprintf("expected int reply, actually %s", result.ToBytes()))
|
t.Error(fmt.Sprintf("expected int protocol, actually %s", result.ToBytes()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if intResult.Code <= 0 {
|
if intResult.Code <= 0 {
|
||||||
@@ -178,9 +178,9 @@ func TestExpireAt(t *testing.T) {
|
|||||||
|
|
||||||
asserts.AssertIntReply(t, result, 1)
|
asserts.AssertIntReply(t, result, 1)
|
||||||
result = testDB.Exec(nil, utils.ToCmdLine("ttl", key))
|
result = testDB.Exec(nil, utils.ToCmdLine("ttl", key))
|
||||||
intResult, ok := result.(*reply.IntReply)
|
intResult, ok := result.(*protocol.IntReply)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Error(fmt.Sprintf("expected int reply, actually %s", result.ToBytes()))
|
t.Error(fmt.Sprintf("expected int protocol, actually %s", result.ToBytes()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if intResult.Code <= 0 {
|
if intResult.Code <= 0 {
|
||||||
@@ -192,9 +192,9 @@ func TestExpireAt(t *testing.T) {
|
|||||||
result = testDB.Exec(nil, utils.ToCmdLine("PExpireAt", key, strconv.FormatInt(expireAt*1000, 10)))
|
result = testDB.Exec(nil, utils.ToCmdLine("PExpireAt", key, strconv.FormatInt(expireAt*1000, 10)))
|
||||||
asserts.AssertIntReply(t, result, 1)
|
asserts.AssertIntReply(t, result, 1)
|
||||||
result = testDB.Exec(nil, utils.ToCmdLine("ttl", key))
|
result = testDB.Exec(nil, utils.ToCmdLine("ttl", key))
|
||||||
intResult, ok = result.(*reply.IntReply)
|
intResult, ok = result.(*protocol.IntReply)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Error(fmt.Sprintf("expected int reply, actually %s", result.ToBytes()))
|
t.Error(fmt.Sprintf("expected int protocol, actually %s", result.ToBytes()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if intResult.Code <= 0 {
|
if intResult.Code <= 0 {
|
||||||
|
@@ -5,23 +5,23 @@ import (
|
|||||||
"github.com/hdt3213/godis/interface/database"
|
"github.com/hdt3213/godis/interface/database"
|
||||||
"github.com/hdt3213/godis/interface/redis"
|
"github.com/hdt3213/godis/interface/redis"
|
||||||
"github.com/hdt3213/godis/lib/utils"
|
"github.com/hdt3213/godis/lib/utils"
|
||||||
"github.com/hdt3213/godis/redis/reply"
|
"github.com/hdt3213/godis/redis/protocol"
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (db *DB) getAsList(key string) (*List.LinkedList, reply.ErrorReply) {
|
func (db *DB) getAsList(key string) (*List.LinkedList, protocol.ErrorReply) {
|
||||||
entity, ok := db.GetEntity(key)
|
entity, ok := db.GetEntity(key)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
bytes, ok := entity.Data.(*List.LinkedList)
|
bytes, ok := entity.Data.(*List.LinkedList)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, &reply.WrongTypeErrReply{}
|
return nil, &protocol.WrongTypeErrReply{}
|
||||||
}
|
}
|
||||||
return bytes, nil
|
return bytes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) getOrInitList(key string) (list *List.LinkedList, isNew bool, errReply reply.ErrorReply) {
|
func (db *DB) getOrInitList(key string) (list *List.LinkedList, isNew bool, errReply protocol.ErrorReply) {
|
||||||
list, errReply = db.getAsList(key)
|
list, errReply = db.getAsList(key)
|
||||||
if errReply != nil {
|
if errReply != nil {
|
||||||
return nil, false, errReply
|
return nil, false, errReply
|
||||||
@@ -43,7 +43,7 @@ func execLIndex(db *DB, args [][]byte) redis.Reply {
|
|||||||
key := string(args[0])
|
key := string(args[0])
|
||||||
index64, err := strconv.ParseInt(string(args[1]), 10, 64)
|
index64, err := strconv.ParseInt(string(args[1]), 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reply.MakeErrReply("ERR value is not an integer or out of range")
|
return protocol.MakeErrReply("ERR value is not an integer or out of range")
|
||||||
}
|
}
|
||||||
index := int(index64)
|
index := int(index64)
|
||||||
|
|
||||||
@@ -53,20 +53,20 @@ func execLIndex(db *DB, args [][]byte) redis.Reply {
|
|||||||
return errReply
|
return errReply
|
||||||
}
|
}
|
||||||
if list == nil {
|
if list == nil {
|
||||||
return &reply.NullBulkReply{}
|
return &protocol.NullBulkReply{}
|
||||||
}
|
}
|
||||||
|
|
||||||
size := list.Len() // assert: size > 0
|
size := list.Len() // assert: size > 0
|
||||||
if index < -1*size {
|
if index < -1*size {
|
||||||
return &reply.NullBulkReply{}
|
return &protocol.NullBulkReply{}
|
||||||
} else if index < 0 {
|
} else if index < 0 {
|
||||||
index = size + index
|
index = size + index
|
||||||
} else if index >= size {
|
} else if index >= size {
|
||||||
return &reply.NullBulkReply{}
|
return &protocol.NullBulkReply{}
|
||||||
}
|
}
|
||||||
|
|
||||||
val, _ := list.Get(index).([]byte)
|
val, _ := list.Get(index).([]byte)
|
||||||
return reply.MakeBulkReply(val)
|
return protocol.MakeBulkReply(val)
|
||||||
}
|
}
|
||||||
|
|
||||||
// execLLen gets length of list
|
// execLLen gets length of list
|
||||||
@@ -79,11 +79,11 @@ func execLLen(db *DB, args [][]byte) redis.Reply {
|
|||||||
return errReply
|
return errReply
|
||||||
}
|
}
|
||||||
if list == nil {
|
if list == nil {
|
||||||
return reply.MakeIntReply(0)
|
return protocol.MakeIntReply(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
size := int64(list.Len())
|
size := int64(list.Len())
|
||||||
return reply.MakeIntReply(size)
|
return protocol.MakeIntReply(size)
|
||||||
}
|
}
|
||||||
|
|
||||||
// execLPop removes the first element of list, and return it
|
// execLPop removes the first element of list, and return it
|
||||||
@@ -97,7 +97,7 @@ func execLPop(db *DB, args [][]byte) redis.Reply {
|
|||||||
return errReply
|
return errReply
|
||||||
}
|
}
|
||||||
if list == nil {
|
if list == nil {
|
||||||
return &reply.NullBulkReply{}
|
return &protocol.NullBulkReply{}
|
||||||
}
|
}
|
||||||
|
|
||||||
val, _ := list.Remove(0).([]byte)
|
val, _ := list.Remove(0).([]byte)
|
||||||
@@ -105,7 +105,7 @@ func execLPop(db *DB, args [][]byte) redis.Reply {
|
|||||||
db.Remove(key)
|
db.Remove(key)
|
||||||
}
|
}
|
||||||
db.addAof(utils.ToCmdLine3("lpop", args...))
|
db.addAof(utils.ToCmdLine3("lpop", args...))
|
||||||
return reply.MakeBulkReply(val)
|
return protocol.MakeBulkReply(val)
|
||||||
}
|
}
|
||||||
|
|
||||||
var lPushCmd = []byte("LPUSH")
|
var lPushCmd = []byte("LPUSH")
|
||||||
@@ -146,7 +146,7 @@ func execLPush(db *DB, args [][]byte) redis.Reply {
|
|||||||
}
|
}
|
||||||
|
|
||||||
db.addAof(utils.ToCmdLine3("lpush", args...))
|
db.addAof(utils.ToCmdLine3("lpush", args...))
|
||||||
return reply.MakeIntReply(int64(list.Len()))
|
return protocol.MakeIntReply(int64(list.Len()))
|
||||||
}
|
}
|
||||||
|
|
||||||
func undoLPush(db *DB, args [][]byte) []CmdLine {
|
func undoLPush(db *DB, args [][]byte) []CmdLine {
|
||||||
@@ -170,7 +170,7 @@ func execLPushX(db *DB, args [][]byte) redis.Reply {
|
|||||||
return errReply
|
return errReply
|
||||||
}
|
}
|
||||||
if list == nil {
|
if list == nil {
|
||||||
return reply.MakeIntReply(0)
|
return protocol.MakeIntReply(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// insert
|
// insert
|
||||||
@@ -178,7 +178,7 @@ func execLPushX(db *DB, args [][]byte) redis.Reply {
|
|||||||
list.Insert(0, value)
|
list.Insert(0, value)
|
||||||
}
|
}
|
||||||
db.addAof(utils.ToCmdLine3("lpushx", args...))
|
db.addAof(utils.ToCmdLine3("lpushx", args...))
|
||||||
return reply.MakeIntReply(int64(list.Len()))
|
return protocol.MakeIntReply(int64(list.Len()))
|
||||||
}
|
}
|
||||||
|
|
||||||
// execLRange gets elements of list in given range
|
// execLRange gets elements of list in given range
|
||||||
@@ -187,12 +187,12 @@ func execLRange(db *DB, args [][]byte) redis.Reply {
|
|||||||
key := string(args[0])
|
key := string(args[0])
|
||||||
start64, err := strconv.ParseInt(string(args[1]), 10, 64)
|
start64, err := strconv.ParseInt(string(args[1]), 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reply.MakeErrReply("ERR value is not an integer or out of range")
|
return protocol.MakeErrReply("ERR value is not an integer or out of range")
|
||||||
}
|
}
|
||||||
start := int(start64)
|
start := int(start64)
|
||||||
stop64, err := strconv.ParseInt(string(args[2]), 10, 64)
|
stop64, err := strconv.ParseInt(string(args[2]), 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reply.MakeErrReply("ERR value is not an integer or out of range")
|
return protocol.MakeErrReply("ERR value is not an integer or out of range")
|
||||||
}
|
}
|
||||||
stop := int(stop64)
|
stop := int(stop64)
|
||||||
|
|
||||||
@@ -202,7 +202,7 @@ func execLRange(db *DB, args [][]byte) redis.Reply {
|
|||||||
return errReply
|
return errReply
|
||||||
}
|
}
|
||||||
if list == nil {
|
if list == nil {
|
||||||
return &reply.EmptyMultiBulkReply{}
|
return &protocol.EmptyMultiBulkReply{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// compute index
|
// compute index
|
||||||
@@ -212,7 +212,7 @@ func execLRange(db *DB, args [][]byte) redis.Reply {
|
|||||||
} else if start < 0 {
|
} else if start < 0 {
|
||||||
start = size + start
|
start = size + start
|
||||||
} else if start >= size {
|
} else if start >= size {
|
||||||
return &reply.EmptyMultiBulkReply{}
|
return &protocol.EmptyMultiBulkReply{}
|
||||||
}
|
}
|
||||||
if stop < -1*size {
|
if stop < -1*size {
|
||||||
stop = 0
|
stop = 0
|
||||||
@@ -234,7 +234,7 @@ func execLRange(db *DB, args [][]byte) redis.Reply {
|
|||||||
bytes, _ := raw.([]byte)
|
bytes, _ := raw.([]byte)
|
||||||
result[i] = bytes
|
result[i] = bytes
|
||||||
}
|
}
|
||||||
return reply.MakeMultiBulkReply(result)
|
return protocol.MakeMultiBulkReply(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
// execLRem removes element of list at specified index
|
// execLRem removes element of list at specified index
|
||||||
@@ -243,7 +243,7 @@ func execLRem(db *DB, args [][]byte) redis.Reply {
|
|||||||
key := string(args[0])
|
key := string(args[0])
|
||||||
count64, err := strconv.ParseInt(string(args[1]), 10, 64)
|
count64, err := strconv.ParseInt(string(args[1]), 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reply.MakeErrReply("ERR value is not an integer or out of range")
|
return protocol.MakeErrReply("ERR value is not an integer or out of range")
|
||||||
}
|
}
|
||||||
count := int(count64)
|
count := int(count64)
|
||||||
value := args[2]
|
value := args[2]
|
||||||
@@ -254,7 +254,7 @@ func execLRem(db *DB, args [][]byte) redis.Reply {
|
|||||||
return errReply
|
return errReply
|
||||||
}
|
}
|
||||||
if list == nil {
|
if list == nil {
|
||||||
return reply.MakeIntReply(0)
|
return protocol.MakeIntReply(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
var removed int
|
var removed int
|
||||||
@@ -273,7 +273,7 @@ func execLRem(db *DB, args [][]byte) redis.Reply {
|
|||||||
db.addAof(utils.ToCmdLine3("lrem", args...))
|
db.addAof(utils.ToCmdLine3("lrem", args...))
|
||||||
}
|
}
|
||||||
|
|
||||||
return reply.MakeIntReply(int64(removed))
|
return protocol.MakeIntReply(int64(removed))
|
||||||
}
|
}
|
||||||
|
|
||||||
// execLSet puts element at specified index of list
|
// execLSet puts element at specified index of list
|
||||||
@@ -282,7 +282,7 @@ func execLSet(db *DB, args [][]byte) redis.Reply {
|
|||||||
key := string(args[0])
|
key := string(args[0])
|
||||||
index64, err := strconv.ParseInt(string(args[1]), 10, 64)
|
index64, err := strconv.ParseInt(string(args[1]), 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reply.MakeErrReply("ERR value is not an integer or out of range")
|
return protocol.MakeErrReply("ERR value is not an integer or out of range")
|
||||||
}
|
}
|
||||||
index := int(index64)
|
index := int(index64)
|
||||||
value := args[2]
|
value := args[2]
|
||||||
@@ -293,21 +293,21 @@ func execLSet(db *DB, args [][]byte) redis.Reply {
|
|||||||
return errReply
|
return errReply
|
||||||
}
|
}
|
||||||
if list == nil {
|
if list == nil {
|
||||||
return reply.MakeErrReply("ERR no such key")
|
return protocol.MakeErrReply("ERR no such key")
|
||||||
}
|
}
|
||||||
|
|
||||||
size := list.Len() // assert: size > 0
|
size := list.Len() // assert: size > 0
|
||||||
if index < -1*size {
|
if index < -1*size {
|
||||||
return reply.MakeErrReply("ERR index out of range")
|
return protocol.MakeErrReply("ERR index out of range")
|
||||||
} else if index < 0 {
|
} else if index < 0 {
|
||||||
index = size + index
|
index = size + index
|
||||||
} else if index >= size {
|
} else if index >= size {
|
||||||
return reply.MakeErrReply("ERR index out of range")
|
return protocol.MakeErrReply("ERR index out of range")
|
||||||
}
|
}
|
||||||
|
|
||||||
list.Set(index, value)
|
list.Set(index, value)
|
||||||
db.addAof(utils.ToCmdLine3("lset", args...))
|
db.addAof(utils.ToCmdLine3("lset", args...))
|
||||||
return &reply.OkReply{}
|
return &protocol.OkReply{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func undoLSet(db *DB, args [][]byte) []CmdLine {
|
func undoLSet(db *DB, args [][]byte) []CmdLine {
|
||||||
@@ -354,7 +354,7 @@ func execRPop(db *DB, args [][]byte) redis.Reply {
|
|||||||
return errReply
|
return errReply
|
||||||
}
|
}
|
||||||
if list == nil {
|
if list == nil {
|
||||||
return &reply.NullBulkReply{}
|
return &protocol.NullBulkReply{}
|
||||||
}
|
}
|
||||||
|
|
||||||
val, _ := list.RemoveLast().([]byte)
|
val, _ := list.RemoveLast().([]byte)
|
||||||
@@ -362,7 +362,7 @@ func execRPop(db *DB, args [][]byte) redis.Reply {
|
|||||||
db.Remove(key)
|
db.Remove(key)
|
||||||
}
|
}
|
||||||
db.addAof(utils.ToCmdLine3("rpop", args...))
|
db.addAof(utils.ToCmdLine3("rpop", args...))
|
||||||
return reply.MakeBulkReply(val)
|
return protocol.MakeBulkReply(val)
|
||||||
}
|
}
|
||||||
|
|
||||||
var rPushCmd = []byte("RPUSH")
|
var rPushCmd = []byte("RPUSH")
|
||||||
@@ -404,7 +404,7 @@ func execRPopLPush(db *DB, args [][]byte) redis.Reply {
|
|||||||
return errReply
|
return errReply
|
||||||
}
|
}
|
||||||
if sourceList == nil {
|
if sourceList == nil {
|
||||||
return &reply.NullBulkReply{}
|
return &protocol.NullBulkReply{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// get dest entity
|
// get dest entity
|
||||||
@@ -422,7 +422,7 @@ func execRPopLPush(db *DB, args [][]byte) redis.Reply {
|
|||||||
}
|
}
|
||||||
|
|
||||||
db.addAof(utils.ToCmdLine3("rpoplpush", args...))
|
db.addAof(utils.ToCmdLine3("rpoplpush", args...))
|
||||||
return reply.MakeBulkReply(val)
|
return protocol.MakeBulkReply(val)
|
||||||
}
|
}
|
||||||
|
|
||||||
func undoRPopLPush(db *DB, args [][]byte) []CmdLine {
|
func undoRPopLPush(db *DB, args [][]byte) []CmdLine {
|
||||||
@@ -465,7 +465,7 @@ func execRPush(db *DB, args [][]byte) redis.Reply {
|
|||||||
list.Add(value)
|
list.Add(value)
|
||||||
}
|
}
|
||||||
db.addAof(utils.ToCmdLine3("rpush", args...))
|
db.addAof(utils.ToCmdLine3("rpush", args...))
|
||||||
return reply.MakeIntReply(int64(list.Len()))
|
return protocol.MakeIntReply(int64(list.Len()))
|
||||||
}
|
}
|
||||||
|
|
||||||
func undoRPush(db *DB, args [][]byte) []CmdLine {
|
func undoRPush(db *DB, args [][]byte) []CmdLine {
|
||||||
@@ -481,7 +481,7 @@ func undoRPush(db *DB, args [][]byte) []CmdLine {
|
|||||||
// execRPushX inserts element at last of list only if list exists
|
// execRPushX inserts element at last of list only if list exists
|
||||||
func execRPushX(db *DB, args [][]byte) redis.Reply {
|
func execRPushX(db *DB, args [][]byte) redis.Reply {
|
||||||
if len(args) < 2 {
|
if len(args) < 2 {
|
||||||
return reply.MakeErrReply("ERR wrong number of arguments for 'rpush' command")
|
return protocol.MakeErrReply("ERR wrong number of arguments for 'rpush' command")
|
||||||
}
|
}
|
||||||
key := string(args[0])
|
key := string(args[0])
|
||||||
values := args[1:]
|
values := args[1:]
|
||||||
@@ -492,7 +492,7 @@ func execRPushX(db *DB, args [][]byte) redis.Reply {
|
|||||||
return errReply
|
return errReply
|
||||||
}
|
}
|
||||||
if list == nil {
|
if list == nil {
|
||||||
return reply.MakeIntReply(0)
|
return protocol.MakeIntReply(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// put list
|
// put list
|
||||||
@@ -501,7 +501,7 @@ func execRPushX(db *DB, args [][]byte) redis.Reply {
|
|||||||
}
|
}
|
||||||
db.addAof(utils.ToCmdLine3("rpushx", args...))
|
db.addAof(utils.ToCmdLine3("rpushx", args...))
|
||||||
|
|
||||||
return reply.MakeIntReply(int64(list.Len()))
|
return protocol.MakeIntReply(int64(list.Len()))
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@@ -3,8 +3,8 @@ package database
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/hdt3213/godis/lib/utils"
|
"github.com/hdt3213/godis/lib/utils"
|
||||||
"github.com/hdt3213/godis/redis/reply"
|
"github.com/hdt3213/godis/redis/protocol"
|
||||||
"github.com/hdt3213/godis/redis/reply/asserts"
|
"github.com/hdt3213/godis/redis/protocol/asserts"
|
||||||
"strconv"
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
@@ -20,12 +20,12 @@ func TestPush(t *testing.T) {
|
|||||||
value := utils.RandString(10)
|
value := utils.RandString(10)
|
||||||
values[i] = []byte(value)
|
values[i] = []byte(value)
|
||||||
result := testDB.Exec(nil, utils.ToCmdLine("rpush", key, value))
|
result := testDB.Exec(nil, utils.ToCmdLine("rpush", key, value))
|
||||||
if intResult, _ := result.(*reply.IntReply); intResult.Code != int64(i+1) {
|
if intResult, _ := result.(*protocol.IntReply); intResult.Code != int64(i+1) {
|
||||||
t.Error(fmt.Sprintf("expected %d, actually %d", i+1, intResult.Code))
|
t.Error(fmt.Sprintf("expected %d, actually %d", i+1, intResult.Code))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actual := testDB.Exec(nil, utils.ToCmdLine("lrange", key, "0", "-1"))
|
actual := testDB.Exec(nil, utils.ToCmdLine("lrange", key, "0", "-1"))
|
||||||
expected := reply.MakeMultiBulkReply(values)
|
expected := protocol.MakeMultiBulkReply(values)
|
||||||
if !utils.BytesEquals(actual.ToBytes(), expected.ToBytes()) {
|
if !utils.BytesEquals(actual.ToBytes(), expected.ToBytes()) {
|
||||||
t.Error("push error")
|
t.Error("push error")
|
||||||
}
|
}
|
||||||
@@ -42,11 +42,11 @@ func TestPush(t *testing.T) {
|
|||||||
args[i+1] = value
|
args[i+1] = value
|
||||||
}
|
}
|
||||||
result := testDB.Exec(nil, utils.ToCmdLine2("rpush", args...))
|
result := testDB.Exec(nil, utils.ToCmdLine2("rpush", args...))
|
||||||
if intResult, _ := result.(*reply.IntReply); intResult.Code != int64(size) {
|
if intResult, _ := result.(*protocol.IntReply); intResult.Code != int64(size) {
|
||||||
t.Error(fmt.Sprintf("expected %d, actually %d", size, intResult.Code))
|
t.Error(fmt.Sprintf("expected %d, actually %d", size, intResult.Code))
|
||||||
}
|
}
|
||||||
actual = testDB.Exec(nil, utils.ToCmdLine("lrange", key, "0", "-1"))
|
actual = testDB.Exec(nil, utils.ToCmdLine("lrange", key, "0", "-1"))
|
||||||
expected = reply.MakeMultiBulkReply(values)
|
expected = protocol.MakeMultiBulkReply(values)
|
||||||
if !utils.BytesEquals(actual.ToBytes(), expected.ToBytes()) {
|
if !utils.BytesEquals(actual.ToBytes(), expected.ToBytes()) {
|
||||||
t.Error("push error")
|
t.Error("push error")
|
||||||
}
|
}
|
||||||
@@ -59,12 +59,12 @@ func TestPush(t *testing.T) {
|
|||||||
value := utils.RandString(10)
|
value := utils.RandString(10)
|
||||||
values[size-i-1] = []byte(value)
|
values[size-i-1] = []byte(value)
|
||||||
result = testDB.Exec(nil, utils.ToCmdLine("lpush", key, value))
|
result = testDB.Exec(nil, utils.ToCmdLine("lpush", key, value))
|
||||||
if intResult, _ := result.(*reply.IntReply); intResult.Code != int64(i+1) {
|
if intResult, _ := result.(*protocol.IntReply); intResult.Code != int64(i+1) {
|
||||||
t.Error(fmt.Sprintf("expected %d, actually %d", i+1, intResult.Code))
|
t.Error(fmt.Sprintf("expected %d, actually %d", i+1, intResult.Code))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
actual = testDB.Exec(nil, utils.ToCmdLine("lrange", key, "0", "-1"))
|
actual = testDB.Exec(nil, utils.ToCmdLine("lrange", key, "0", "-1"))
|
||||||
expected = reply.MakeMultiBulkReply(values)
|
expected = protocol.MakeMultiBulkReply(values)
|
||||||
if !utils.BytesEquals(actual.ToBytes(), expected.ToBytes()) {
|
if !utils.BytesEquals(actual.ToBytes(), expected.ToBytes()) {
|
||||||
t.Error("push error")
|
t.Error("push error")
|
||||||
}
|
}
|
||||||
@@ -82,11 +82,11 @@ func TestPush(t *testing.T) {
|
|||||||
}
|
}
|
||||||
result = execLPush(testDB, values)
|
result = execLPush(testDB, values)
|
||||||
result = testDB.Exec(nil, utils.ToCmdLine2("lpush", args...))
|
result = testDB.Exec(nil, utils.ToCmdLine2("lpush", args...))
|
||||||
if intResult, _ := result.(*reply.IntReply); intResult.Code != int64(size) {
|
if intResult, _ := result.(*protocol.IntReply); intResult.Code != int64(size) {
|
||||||
t.Error(fmt.Sprintf("expected %d, actually %d", size, intResult.Code))
|
t.Error(fmt.Sprintf("expected %d, actually %d", size, intResult.Code))
|
||||||
}
|
}
|
||||||
actual = testDB.Exec(nil, utils.ToCmdLine("lrange", key, "0", "-1"))
|
actual = testDB.Exec(nil, utils.ToCmdLine("lrange", key, "0", "-1"))
|
||||||
expected = reply.MakeMultiBulkReply(expectedValues)
|
expected = protocol.MakeMultiBulkReply(expectedValues)
|
||||||
if !utils.BytesEquals(actual.ToBytes(), expected.ToBytes()) {
|
if !utils.BytesEquals(actual.ToBytes(), expected.ToBytes()) {
|
||||||
t.Error("push error")
|
t.Error("push error")
|
||||||
}
|
}
|
||||||
@@ -108,7 +108,7 @@ func TestLRange(t *testing.T) {
|
|||||||
start := "0"
|
start := "0"
|
||||||
end := "9"
|
end := "9"
|
||||||
actual := testDB.Exec(nil, utils.ToCmdLine("lrange", key, start, end))
|
actual := testDB.Exec(nil, utils.ToCmdLine("lrange", key, start, end))
|
||||||
expected := reply.MakeMultiBulkReply(values[0:10])
|
expected := protocol.MakeMultiBulkReply(values[0:10])
|
||||||
if !utils.BytesEquals(actual.ToBytes(), expected.ToBytes()) {
|
if !utils.BytesEquals(actual.ToBytes(), expected.ToBytes()) {
|
||||||
t.Error(fmt.Sprintf("range error [%s, %s]", start, end))
|
t.Error(fmt.Sprintf("range error [%s, %s]", start, end))
|
||||||
}
|
}
|
||||||
@@ -116,7 +116,7 @@ func TestLRange(t *testing.T) {
|
|||||||
start = "0"
|
start = "0"
|
||||||
end = "200"
|
end = "200"
|
||||||
actual = testDB.Exec(nil, utils.ToCmdLine("lrange", key, start, end))
|
actual = testDB.Exec(nil, utils.ToCmdLine("lrange", key, start, end))
|
||||||
expected = reply.MakeMultiBulkReply(values)
|
expected = protocol.MakeMultiBulkReply(values)
|
||||||
if !utils.BytesEquals(actual.ToBytes(), expected.ToBytes()) {
|
if !utils.BytesEquals(actual.ToBytes(), expected.ToBytes()) {
|
||||||
t.Error(fmt.Sprintf("range error [%s, %s]", start, end))
|
t.Error(fmt.Sprintf("range error [%s, %s]", start, end))
|
||||||
}
|
}
|
||||||
@@ -124,7 +124,7 @@ func TestLRange(t *testing.T) {
|
|||||||
start = "0"
|
start = "0"
|
||||||
end = "-10"
|
end = "-10"
|
||||||
actual = testDB.Exec(nil, utils.ToCmdLine("lrange", key, start, end))
|
actual = testDB.Exec(nil, utils.ToCmdLine("lrange", key, start, end))
|
||||||
expected = reply.MakeMultiBulkReply(values[0 : size-10+1])
|
expected = protocol.MakeMultiBulkReply(values[0 : size-10+1])
|
||||||
if !utils.BytesEquals(actual.ToBytes(), expected.ToBytes()) {
|
if !utils.BytesEquals(actual.ToBytes(), expected.ToBytes()) {
|
||||||
t.Error(fmt.Sprintf("range error [%s, %s]", start, end))
|
t.Error(fmt.Sprintf("range error [%s, %s]", start, end))
|
||||||
}
|
}
|
||||||
@@ -132,7 +132,7 @@ func TestLRange(t *testing.T) {
|
|||||||
start = "0"
|
start = "0"
|
||||||
end = "-200"
|
end = "-200"
|
||||||
actual = testDB.Exec(nil, utils.ToCmdLine("lrange", key, start, end))
|
actual = testDB.Exec(nil, utils.ToCmdLine("lrange", key, start, end))
|
||||||
expected = reply.MakeMultiBulkReply(values[0:0])
|
expected = protocol.MakeMultiBulkReply(values[0:0])
|
||||||
if !utils.BytesEquals(actual.ToBytes(), expected.ToBytes()) {
|
if !utils.BytesEquals(actual.ToBytes(), expected.ToBytes()) {
|
||||||
t.Error(fmt.Sprintf("range error [%s, %s]", start, end))
|
t.Error(fmt.Sprintf("range error [%s, %s]", start, end))
|
||||||
}
|
}
|
||||||
@@ -140,7 +140,7 @@ func TestLRange(t *testing.T) {
|
|||||||
start = "-10"
|
start = "-10"
|
||||||
end = "-1"
|
end = "-1"
|
||||||
actual = testDB.Exec(nil, utils.ToCmdLine("lrange", key, start, end))
|
actual = testDB.Exec(nil, utils.ToCmdLine("lrange", key, start, end))
|
||||||
expected = reply.MakeMultiBulkReply(values[90:])
|
expected = protocol.MakeMultiBulkReply(values[90:])
|
||||||
if !utils.BytesEquals(actual.ToBytes(), expected.ToBytes()) {
|
if !utils.BytesEquals(actual.ToBytes(), expected.ToBytes()) {
|
||||||
t.Error(fmt.Sprintf("range error [%s, %s]", start, end))
|
t.Error(fmt.Sprintf("range error [%s, %s]", start, end))
|
||||||
}
|
}
|
||||||
@@ -159,13 +159,13 @@ func TestLIndex(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
result := testDB.Exec(nil, utils.ToCmdLine("llen", key))
|
result := testDB.Exec(nil, utils.ToCmdLine("llen", key))
|
||||||
if intResult, _ := result.(*reply.IntReply); intResult.Code != int64(size) {
|
if intResult, _ := result.(*protocol.IntReply); intResult.Code != int64(size) {
|
||||||
t.Error(fmt.Sprintf("expected %d, actually %d", size, intResult.Code))
|
t.Error(fmt.Sprintf("expected %d, actually %d", size, intResult.Code))
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < size; i++ {
|
for i := 0; i < size; i++ {
|
||||||
result = testDB.Exec(nil, utils.ToCmdLine("lindex", key, strconv.Itoa(i)))
|
result = testDB.Exec(nil, utils.ToCmdLine("lindex", key, strconv.Itoa(i)))
|
||||||
expected := reply.MakeBulkReply(values[i])
|
expected := protocol.MakeBulkReply(values[i])
|
||||||
if !utils.BytesEquals(result.ToBytes(), expected.ToBytes()) {
|
if !utils.BytesEquals(result.ToBytes(), expected.ToBytes()) {
|
||||||
t.Error(fmt.Sprintf("expected %s, actually %s", string(expected.ToBytes()), string(result.ToBytes())))
|
t.Error(fmt.Sprintf("expected %s, actually %s", string(expected.ToBytes()), string(result.ToBytes())))
|
||||||
}
|
}
|
||||||
@@ -173,7 +173,7 @@ func TestLIndex(t *testing.T) {
|
|||||||
|
|
||||||
for i := 1; i <= size; i++ {
|
for i := 1; i <= size; i++ {
|
||||||
result = testDB.Exec(nil, utils.ToCmdLine("lindex", key, strconv.Itoa(-i)))
|
result = testDB.Exec(nil, utils.ToCmdLine("lindex", key, strconv.Itoa(-i)))
|
||||||
expected := reply.MakeBulkReply(values[size-i])
|
expected := protocol.MakeBulkReply(values[size-i])
|
||||||
if !utils.BytesEquals(result.ToBytes(), expected.ToBytes()) {
|
if !utils.BytesEquals(result.ToBytes(), expected.ToBytes()) {
|
||||||
t.Error(fmt.Sprintf("expected %s, actually %s", string(expected.ToBytes()), string(result.ToBytes())))
|
t.Error(fmt.Sprintf("expected %s, actually %s", string(expected.ToBytes()), string(result.ToBytes())))
|
||||||
}
|
}
|
||||||
@@ -188,29 +188,29 @@ func TestLRem(t *testing.T) {
|
|||||||
testDB.Exec(nil, utils.ToCmdLine2("rpush", values...))
|
testDB.Exec(nil, utils.ToCmdLine2("rpush", values...))
|
||||||
|
|
||||||
result := testDB.Exec(nil, utils.ToCmdLine("lrem", key, "1", "a"))
|
result := testDB.Exec(nil, utils.ToCmdLine("lrem", key, "1", "a"))
|
||||||
if intResult, _ := result.(*reply.IntReply); intResult.Code != 1 {
|
if intResult, _ := result.(*protocol.IntReply); intResult.Code != 1 {
|
||||||
t.Error(fmt.Sprintf("expected %d, actually %d", 1, intResult.Code))
|
t.Error(fmt.Sprintf("expected %d, actually %d", 1, intResult.Code))
|
||||||
}
|
}
|
||||||
result = testDB.Exec(nil, utils.ToCmdLine("llen", key))
|
result = testDB.Exec(nil, utils.ToCmdLine("llen", key))
|
||||||
if intResult, _ := result.(*reply.IntReply); intResult.Code != 6 {
|
if intResult, _ := result.(*protocol.IntReply); intResult.Code != 6 {
|
||||||
t.Error(fmt.Sprintf("expected %d, actually %d", 6, intResult.Code))
|
t.Error(fmt.Sprintf("expected %d, actually %d", 6, intResult.Code))
|
||||||
}
|
}
|
||||||
|
|
||||||
result = testDB.Exec(nil, utils.ToCmdLine("lrem", key, "-2", "a"))
|
result = testDB.Exec(nil, utils.ToCmdLine("lrem", key, "-2", "a"))
|
||||||
if intResult, _ := result.(*reply.IntReply); intResult.Code != 2 {
|
if intResult, _ := result.(*protocol.IntReply); intResult.Code != 2 {
|
||||||
t.Error(fmt.Sprintf("expected %d, actually %d", 2, intResult.Code))
|
t.Error(fmt.Sprintf("expected %d, actually %d", 2, intResult.Code))
|
||||||
}
|
}
|
||||||
result = testDB.Exec(nil, utils.ToCmdLine("llen", key))
|
result = testDB.Exec(nil, utils.ToCmdLine("llen", key))
|
||||||
if intResult, _ := result.(*reply.IntReply); intResult.Code != 4 {
|
if intResult, _ := result.(*protocol.IntReply); intResult.Code != 4 {
|
||||||
t.Error(fmt.Sprintf("expected %d, actually %d", 4, intResult.Code))
|
t.Error(fmt.Sprintf("expected %d, actually %d", 4, intResult.Code))
|
||||||
}
|
}
|
||||||
|
|
||||||
result = testDB.Exec(nil, utils.ToCmdLine("lrem", key, "0", "a"))
|
result = testDB.Exec(nil, utils.ToCmdLine("lrem", key, "0", "a"))
|
||||||
if intResult, _ := result.(*reply.IntReply); intResult.Code != 2 {
|
if intResult, _ := result.(*protocol.IntReply); intResult.Code != 2 {
|
||||||
t.Error(fmt.Sprintf("expected %d, actually %d", 2, intResult.Code))
|
t.Error(fmt.Sprintf("expected %d, actually %d", 2, intResult.Code))
|
||||||
}
|
}
|
||||||
result = testDB.Exec(nil, utils.ToCmdLine("llen", key))
|
result = testDB.Exec(nil, utils.ToCmdLine("llen", key))
|
||||||
if intResult, _ := result.(*reply.IntReply); intResult.Code != 2 {
|
if intResult, _ := result.(*protocol.IntReply); intResult.Code != 2 {
|
||||||
t.Error(fmt.Sprintf("expected %d, actually %d", 2, intResult.Code))
|
t.Error(fmt.Sprintf("expected %d, actually %d", 2, intResult.Code))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -227,11 +227,11 @@ func TestLSet(t *testing.T) {
|
|||||||
indexStr := strconv.Itoa(i)
|
indexStr := strconv.Itoa(i)
|
||||||
value := utils.RandString(10)
|
value := utils.RandString(10)
|
||||||
result := testDB.Exec(nil, utils.ToCmdLine("lset", key, indexStr, value))
|
result := testDB.Exec(nil, utils.ToCmdLine("lset", key, indexStr, value))
|
||||||
if _, ok := result.(*reply.OkReply); !ok {
|
if _, ok := result.(*protocol.OkReply); !ok {
|
||||||
t.Error(fmt.Sprintf("expected OK, actually %s", string(result.ToBytes())))
|
t.Error(fmt.Sprintf("expected OK, actually %s", string(result.ToBytes())))
|
||||||
}
|
}
|
||||||
result = testDB.Exec(nil, utils.ToCmdLine("lindex", key, indexStr))
|
result = testDB.Exec(nil, utils.ToCmdLine("lindex", key, indexStr))
|
||||||
expected := reply.MakeBulkReply([]byte(value))
|
expected := protocol.MakeBulkReply([]byte(value))
|
||||||
if !utils.BytesEquals(result.ToBytes(), expected.ToBytes()) {
|
if !utils.BytesEquals(result.ToBytes(), expected.ToBytes()) {
|
||||||
t.Error(fmt.Sprintf("expected %s, actually %s", string(expected.ToBytes()), string(result.ToBytes())))
|
t.Error(fmt.Sprintf("expected %s, actually %s", string(expected.ToBytes()), string(result.ToBytes())))
|
||||||
}
|
}
|
||||||
@@ -240,11 +240,11 @@ func TestLSet(t *testing.T) {
|
|||||||
for i := 1; i <= size; i++ {
|
for i := 1; i <= size; i++ {
|
||||||
value := utils.RandString(10)
|
value := utils.RandString(10)
|
||||||
result := testDB.Exec(nil, utils.ToCmdLine("lset", key, strconv.Itoa(-i), value))
|
result := testDB.Exec(nil, utils.ToCmdLine("lset", key, strconv.Itoa(-i), value))
|
||||||
if _, ok := result.(*reply.OkReply); !ok {
|
if _, ok := result.(*protocol.OkReply); !ok {
|
||||||
t.Error(fmt.Sprintf("expected OK, actually %s", string(result.ToBytes())))
|
t.Error(fmt.Sprintf("expected OK, actually %s", string(result.ToBytes())))
|
||||||
}
|
}
|
||||||
result = testDB.Exec(nil, utils.ToCmdLine("lindex", key, strconv.Itoa(len(values)-i-1)))
|
result = testDB.Exec(nil, utils.ToCmdLine("lindex", key, strconv.Itoa(len(values)-i-1)))
|
||||||
expected := reply.MakeBulkReply([]byte(value))
|
expected := protocol.MakeBulkReply([]byte(value))
|
||||||
if !utils.BytesEquals(result.ToBytes(), expected.ToBytes()) {
|
if !utils.BytesEquals(result.ToBytes(), expected.ToBytes()) {
|
||||||
t.Error(fmt.Sprintf("expected %s, actually %s", string(expected.ToBytes()), string(result.ToBytes())))
|
t.Error(fmt.Sprintf("expected %s, actually %s", string(expected.ToBytes()), string(result.ToBytes())))
|
||||||
}
|
}
|
||||||
@@ -253,7 +253,7 @@ func TestLSet(t *testing.T) {
|
|||||||
// test illegal index
|
// test illegal index
|
||||||
value := utils.RandString(10)
|
value := utils.RandString(10)
|
||||||
result := testDB.Exec(nil, utils.ToCmdLine("lset", key, strconv.Itoa(-len(values)-1), value))
|
result := testDB.Exec(nil, utils.ToCmdLine("lset", key, strconv.Itoa(-len(values)-1), value))
|
||||||
expected := reply.MakeErrReply("ERR index out of range")
|
expected := protocol.MakeErrReply("ERR index out of range")
|
||||||
if !utils.BytesEquals(result.ToBytes(), expected.ToBytes()) {
|
if !utils.BytesEquals(result.ToBytes(), expected.ToBytes()) {
|
||||||
t.Error(fmt.Sprintf("expected %s, actually %s", string(expected.ToBytes()), string(result.ToBytes())))
|
t.Error(fmt.Sprintf("expected %s, actually %s", string(expected.ToBytes()), string(result.ToBytes())))
|
||||||
}
|
}
|
||||||
@@ -262,7 +262,7 @@ func TestLSet(t *testing.T) {
|
|||||||
t.Error(fmt.Sprintf("expected %s, actually %s", string(expected.ToBytes()), string(result.ToBytes())))
|
t.Error(fmt.Sprintf("expected %s, actually %s", string(expected.ToBytes()), string(result.ToBytes())))
|
||||||
}
|
}
|
||||||
result = testDB.Exec(nil, utils.ToCmdLine("lset", key, "a", value))
|
result = testDB.Exec(nil, utils.ToCmdLine("lset", key, "a", value))
|
||||||
expected = reply.MakeErrReply("ERR value is not an integer or out of range")
|
expected = protocol.MakeErrReply("ERR value is not an integer or out of range")
|
||||||
if !utils.BytesEquals(result.ToBytes(), expected.ToBytes()) {
|
if !utils.BytesEquals(result.ToBytes(), expected.ToBytes()) {
|
||||||
t.Error(fmt.Sprintf("expected %s, actually %s", string(expected.ToBytes()), string(result.ToBytes())))
|
t.Error(fmt.Sprintf("expected %s, actually %s", string(expected.ToBytes()), string(result.ToBytes())))
|
||||||
}
|
}
|
||||||
@@ -277,13 +277,13 @@ func TestLPop(t *testing.T) {
|
|||||||
|
|
||||||
for i := 0; i < size; i++ {
|
for i := 0; i < size; i++ {
|
||||||
result := testDB.Exec(nil, utils.ToCmdLine("lpop", key))
|
result := testDB.Exec(nil, utils.ToCmdLine("lpop", key))
|
||||||
expected := reply.MakeBulkReply([]byte(values[i+1]))
|
expected := protocol.MakeBulkReply([]byte(values[i+1]))
|
||||||
if !utils.BytesEquals(result.ToBytes(), expected.ToBytes()) {
|
if !utils.BytesEquals(result.ToBytes(), expected.ToBytes()) {
|
||||||
t.Error(fmt.Sprintf("expected %s, actually %s", string(expected.ToBytes()), string(result.ToBytes())))
|
t.Error(fmt.Sprintf("expected %s, actually %s", string(expected.ToBytes()), string(result.ToBytes())))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result := testDB.Exec(nil, utils.ToCmdLine("rpop", key))
|
result := testDB.Exec(nil, utils.ToCmdLine("rpop", key))
|
||||||
expected := &reply.NullBulkReply{}
|
expected := &protocol.NullBulkReply{}
|
||||||
if !utils.BytesEquals(result.ToBytes(), expected.ToBytes()) {
|
if !utils.BytesEquals(result.ToBytes(), expected.ToBytes()) {
|
||||||
t.Error(fmt.Sprintf("expected %s, actually %s", string(expected.ToBytes()), string(result.ToBytes())))
|
t.Error(fmt.Sprintf("expected %s, actually %s", string(expected.ToBytes()), string(result.ToBytes())))
|
||||||
}
|
}
|
||||||
@@ -298,13 +298,13 @@ func TestRPop(t *testing.T) {
|
|||||||
|
|
||||||
for i := 0; i < size; i++ {
|
for i := 0; i < size; i++ {
|
||||||
result := testDB.Exec(nil, utils.ToCmdLine("rpop", key))
|
result := testDB.Exec(nil, utils.ToCmdLine("rpop", key))
|
||||||
expected := reply.MakeBulkReply([]byte(values[len(values)-i-1]))
|
expected := protocol.MakeBulkReply([]byte(values[len(values)-i-1]))
|
||||||
if !utils.BytesEquals(result.ToBytes(), expected.ToBytes()) {
|
if !utils.BytesEquals(result.ToBytes(), expected.ToBytes()) {
|
||||||
t.Error(fmt.Sprintf("expected %s, actually %s", string(expected.ToBytes()), string(result.ToBytes())))
|
t.Error(fmt.Sprintf("expected %s, actually %s", string(expected.ToBytes()), string(result.ToBytes())))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result := testDB.Exec(nil, utils.ToCmdLine("rpop", key))
|
result := testDB.Exec(nil, utils.ToCmdLine("rpop", key))
|
||||||
expected := &reply.NullBulkReply{}
|
expected := &protocol.NullBulkReply{}
|
||||||
if !utils.BytesEquals(result.ToBytes(), expected.ToBytes()) {
|
if !utils.BytesEquals(result.ToBytes(), expected.ToBytes()) {
|
||||||
t.Error(fmt.Sprintf("expected %s, actually %s", string(expected.ToBytes()), string(result.ToBytes())))
|
t.Error(fmt.Sprintf("expected %s, actually %s", string(expected.ToBytes()), string(result.ToBytes())))
|
||||||
}
|
}
|
||||||
@@ -320,7 +320,7 @@ func TestRPopLPush(t *testing.T) {
|
|||||||
|
|
||||||
for i := 0; i < size; i++ {
|
for i := 0; i < size; i++ {
|
||||||
result := testDB.Exec(nil, utils.ToCmdLine("rpoplpush", key1, key2))
|
result := testDB.Exec(nil, utils.ToCmdLine("rpoplpush", key1, key2))
|
||||||
expected := reply.MakeBulkReply([]byte(values[len(values)-i-1]))
|
expected := protocol.MakeBulkReply([]byte(values[len(values)-i-1]))
|
||||||
if !utils.BytesEquals(result.ToBytes(), expected.ToBytes()) {
|
if !utils.BytesEquals(result.ToBytes(), expected.ToBytes()) {
|
||||||
t.Error(fmt.Sprintf("expected %s, actually %s", string(expected.ToBytes()), string(result.ToBytes())))
|
t.Error(fmt.Sprintf("expected %s, actually %s", string(expected.ToBytes()), string(result.ToBytes())))
|
||||||
}
|
}
|
||||||
@@ -330,7 +330,7 @@ func TestRPopLPush(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
result := testDB.Exec(nil, utils.ToCmdLine("rpop", key1))
|
result := testDB.Exec(nil, utils.ToCmdLine("rpop", key1))
|
||||||
expected := &reply.NullBulkReply{}
|
expected := &protocol.NullBulkReply{}
|
||||||
if !utils.BytesEquals(result.ToBytes(), expected.ToBytes()) {
|
if !utils.BytesEquals(result.ToBytes(), expected.ToBytes()) {
|
||||||
t.Error(fmt.Sprintf("expected %s, actually %s", string(expected.ToBytes()), string(result.ToBytes())))
|
t.Error(fmt.Sprintf("expected %s, actually %s", string(expected.ToBytes()), string(result.ToBytes())))
|
||||||
}
|
}
|
||||||
@@ -340,7 +340,7 @@ func TestRPushX(t *testing.T) {
|
|||||||
testDB.Flush()
|
testDB.Flush()
|
||||||
key := utils.RandString(10)
|
key := utils.RandString(10)
|
||||||
result := testDB.Exec(nil, utils.ToCmdLine("rpushx", key, "1"))
|
result := testDB.Exec(nil, utils.ToCmdLine("rpushx", key, "1"))
|
||||||
expected := reply.MakeIntReply(int64(0))
|
expected := protocol.MakeIntReply(int64(0))
|
||||||
if !utils.BytesEquals(result.ToBytes(), expected.ToBytes()) {
|
if !utils.BytesEquals(result.ToBytes(), expected.ToBytes()) {
|
||||||
t.Error(fmt.Sprintf("expected %s, actually %s", string(expected.ToBytes()), string(result.ToBytes())))
|
t.Error(fmt.Sprintf("expected %s, actually %s", string(expected.ToBytes()), string(result.ToBytes())))
|
||||||
}
|
}
|
||||||
@@ -349,12 +349,12 @@ func TestRPushX(t *testing.T) {
|
|||||||
for i := 0; i < 10; i++ {
|
for i := 0; i < 10; i++ {
|
||||||
value := utils.RandString(10)
|
value := utils.RandString(10)
|
||||||
result = testDB.Exec(nil, utils.ToCmdLine("rpushx", key, value))
|
result = testDB.Exec(nil, utils.ToCmdLine("rpushx", key, value))
|
||||||
expected := reply.MakeIntReply(int64(i + 2))
|
expected := protocol.MakeIntReply(int64(i + 2))
|
||||||
if !utils.BytesEquals(result.ToBytes(), expected.ToBytes()) {
|
if !utils.BytesEquals(result.ToBytes(), expected.ToBytes()) {
|
||||||
t.Error(fmt.Sprintf("expected %s, actually %s", string(expected.ToBytes()), string(result.ToBytes())))
|
t.Error(fmt.Sprintf("expected %s, actually %s", string(expected.ToBytes()), string(result.ToBytes())))
|
||||||
}
|
}
|
||||||
result = testDB.Exec(nil, utils.ToCmdLine("lindex", key, "-1"))
|
result = testDB.Exec(nil, utils.ToCmdLine("lindex", key, "-1"))
|
||||||
expected2 := reply.MakeBulkReply([]byte(value))
|
expected2 := protocol.MakeBulkReply([]byte(value))
|
||||||
if !utils.BytesEquals(result.ToBytes(), expected2.ToBytes()) {
|
if !utils.BytesEquals(result.ToBytes(), expected2.ToBytes()) {
|
||||||
t.Error(fmt.Sprintf("expected %s, actually %s", string(expected2.ToBytes()), string(result.ToBytes())))
|
t.Error(fmt.Sprintf("expected %s, actually %s", string(expected2.ToBytes()), string(result.ToBytes())))
|
||||||
}
|
}
|
||||||
@@ -365,7 +365,7 @@ func TestLPushX(t *testing.T) {
|
|||||||
testDB.Flush()
|
testDB.Flush()
|
||||||
key := utils.RandString(10)
|
key := utils.RandString(10)
|
||||||
result := testDB.Exec(nil, utils.ToCmdLine("rpushx", key, "1"))
|
result := testDB.Exec(nil, utils.ToCmdLine("rpushx", key, "1"))
|
||||||
expected := reply.MakeIntReply(int64(0))
|
expected := protocol.MakeIntReply(int64(0))
|
||||||
if !utils.BytesEquals(result.ToBytes(), expected.ToBytes()) {
|
if !utils.BytesEquals(result.ToBytes(), expected.ToBytes()) {
|
||||||
t.Error(fmt.Sprintf("expected %s, actually %s", string(expected.ToBytes()), string(result.ToBytes())))
|
t.Error(fmt.Sprintf("expected %s, actually %s", string(expected.ToBytes()), string(result.ToBytes())))
|
||||||
}
|
}
|
||||||
@@ -374,12 +374,12 @@ func TestLPushX(t *testing.T) {
|
|||||||
for i := 0; i < 10; i++ {
|
for i := 0; i < 10; i++ {
|
||||||
value := utils.RandString(10)
|
value := utils.RandString(10)
|
||||||
result = testDB.Exec(nil, utils.ToCmdLine("lpushx", key, value))
|
result = testDB.Exec(nil, utils.ToCmdLine("lpushx", key, value))
|
||||||
expected := reply.MakeIntReply(int64(i + 2))
|
expected := protocol.MakeIntReply(int64(i + 2))
|
||||||
if !utils.BytesEquals(result.ToBytes(), expected.ToBytes()) {
|
if !utils.BytesEquals(result.ToBytes(), expected.ToBytes()) {
|
||||||
t.Error(fmt.Sprintf("expected %s, actually %s", string(expected.ToBytes()), string(result.ToBytes())))
|
t.Error(fmt.Sprintf("expected %s, actually %s", string(expected.ToBytes()), string(result.ToBytes())))
|
||||||
}
|
}
|
||||||
result = testDB.Exec(nil, utils.ToCmdLine("lindex", key, "0"))
|
result = testDB.Exec(nil, utils.ToCmdLine("lindex", key, "0"))
|
||||||
expected2 := reply.MakeBulkReply([]byte(value))
|
expected2 := protocol.MakeBulkReply([]byte(value))
|
||||||
if !utils.BytesEquals(result.ToBytes(), expected2.ToBytes()) {
|
if !utils.BytesEquals(result.ToBytes(), expected2.ToBytes()) {
|
||||||
t.Error(fmt.Sprintf("expected %s, actually %s", string(expected2.ToBytes()), string(result.ToBytes())))
|
t.Error(fmt.Sprintf("expected %s, actually %s", string(expected2.ToBytes()), string(result.ToBytes())))
|
||||||
}
|
}
|
||||||
|
@@ -9,7 +9,7 @@ import (
|
|||||||
"github.com/hdt3213/godis/lib/logger"
|
"github.com/hdt3213/godis/lib/logger"
|
||||||
"github.com/hdt3213/godis/lib/utils"
|
"github.com/hdt3213/godis/lib/utils"
|
||||||
"github.com/hdt3213/godis/pubsub"
|
"github.com/hdt3213/godis/pubsub"
|
||||||
"github.com/hdt3213/godis/redis/reply"
|
"github.com/hdt3213/godis/redis/protocol"
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -74,7 +74,7 @@ func (mdb *MultiDB) Exec(c redis.Connection, cmdLine [][]byte) (result redis.Rep
|
|||||||
defer func() {
|
defer func() {
|
||||||
if err := recover(); err != nil {
|
if err := recover(); err != nil {
|
||||||
logger.Warn(fmt.Sprintf("error occurs: %v\n%s", err, string(debug.Stack())))
|
logger.Warn(fmt.Sprintf("error occurs: %v\n%s", err, string(debug.Stack())))
|
||||||
result = &reply.UnknownErrReply{}
|
result = &protocol.UnknownErrReply{}
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
@@ -84,13 +84,13 @@ func (mdb *MultiDB) Exec(c redis.Connection, cmdLine [][]byte) (result redis.Rep
|
|||||||
return Auth(c, cmdLine[1:])
|
return Auth(c, cmdLine[1:])
|
||||||
}
|
}
|
||||||
if !isAuthenticated(c) {
|
if !isAuthenticated(c) {
|
||||||
return reply.MakeErrReply("NOAUTH Authentication required")
|
return protocol.MakeErrReply("NOAUTH Authentication required")
|
||||||
}
|
}
|
||||||
|
|
||||||
// special commands
|
// special commands
|
||||||
if cmdName == "subscribe" {
|
if cmdName == "subscribe" {
|
||||||
if len(cmdLine) < 2 {
|
if len(cmdLine) < 2 {
|
||||||
return reply.MakeArgNumErrReply("subscribe")
|
return protocol.MakeArgNumErrReply("subscribe")
|
||||||
}
|
}
|
||||||
return pubsub.Subscribe(mdb.hub, c, cmdLine[1:])
|
return pubsub.Subscribe(mdb.hub, c, cmdLine[1:])
|
||||||
} else if cmdName == "publish" {
|
} else if cmdName == "publish" {
|
||||||
@@ -106,10 +106,10 @@ func (mdb *MultiDB) Exec(c redis.Connection, cmdLine [][]byte) (result redis.Rep
|
|||||||
return mdb.flushAll()
|
return mdb.flushAll()
|
||||||
} else if cmdName == "select" {
|
} else if cmdName == "select" {
|
||||||
if c != nil && c.InMultiState() {
|
if c != nil && c.InMultiState() {
|
||||||
return reply.MakeErrReply("cannot select database within multi")
|
return protocol.MakeErrReply("cannot select database within multi")
|
||||||
}
|
}
|
||||||
if len(cmdLine) != 2 {
|
if len(cmdLine) != 2 {
|
||||||
return reply.MakeArgNumErrReply("select")
|
return protocol.MakeArgNumErrReply("select")
|
||||||
}
|
}
|
||||||
return execSelect(c, mdb, cmdLine[1:])
|
return execSelect(c, mdb, cmdLine[1:])
|
||||||
}
|
}
|
||||||
@@ -118,7 +118,7 @@ func (mdb *MultiDB) Exec(c redis.Connection, cmdLine [][]byte) (result redis.Rep
|
|||||||
// normal commands
|
// normal commands
|
||||||
dbIndex := c.GetDBIndex()
|
dbIndex := c.GetDBIndex()
|
||||||
if dbIndex >= len(mdb.dbSet) {
|
if dbIndex >= len(mdb.dbSet) {
|
||||||
return reply.MakeErrReply("ERR DB index is out of range")
|
return protocol.MakeErrReply("ERR DB index is out of range")
|
||||||
}
|
}
|
||||||
selectedDB := mdb.dbSet[dbIndex]
|
selectedDB := mdb.dbSet[dbIndex]
|
||||||
return selectedDB.Exec(c, cmdLine)
|
return selectedDB.Exec(c, cmdLine)
|
||||||
@@ -139,13 +139,13 @@ func (mdb *MultiDB) Close() {
|
|||||||
func execSelect(c redis.Connection, mdb *MultiDB, args [][]byte) redis.Reply {
|
func execSelect(c redis.Connection, mdb *MultiDB, args [][]byte) redis.Reply {
|
||||||
dbIndex, err := strconv.Atoi(string(args[0]))
|
dbIndex, err := strconv.Atoi(string(args[0]))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reply.MakeErrReply("ERR invalid DB index")
|
return protocol.MakeErrReply("ERR invalid DB index")
|
||||||
}
|
}
|
||||||
if dbIndex >= len(mdb.dbSet) {
|
if dbIndex >= len(mdb.dbSet) {
|
||||||
return reply.MakeErrReply("ERR DB index is out of range")
|
return protocol.MakeErrReply("ERR DB index is out of range")
|
||||||
}
|
}
|
||||||
c.SelectDB(dbIndex)
|
c.SelectDB(dbIndex)
|
||||||
return reply.MakeOkReply()
|
return protocol.MakeOkReply()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mdb *MultiDB) flushAll() redis.Reply {
|
func (mdb *MultiDB) flushAll() redis.Reply {
|
||||||
@@ -155,7 +155,7 @@ func (mdb *MultiDB) flushAll() redis.Reply {
|
|||||||
if mdb.aofHandler != nil {
|
if mdb.aofHandler != nil {
|
||||||
mdb.aofHandler.AddAof(0, utils.ToCmdLine("FlushAll"))
|
mdb.aofHandler.AddAof(0, utils.ToCmdLine("FlushAll"))
|
||||||
}
|
}
|
||||||
return &reply.OkReply{}
|
return &protocol.OkReply{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ForEach traverses all the keys in the given database
|
// ForEach traverses all the keys in the given database
|
||||||
@@ -170,7 +170,7 @@ func (mdb *MultiDB) ForEach(dbIndex int, cb func(key string, data *database.Data
|
|||||||
// ExecMulti executes multi commands transaction Atomically and Isolated
|
// ExecMulti executes multi commands transaction Atomically and Isolated
|
||||||
func (mdb *MultiDB) ExecMulti(conn redis.Connection, watching map[string]uint32, cmdLines []CmdLine) redis.Reply {
|
func (mdb *MultiDB) ExecMulti(conn redis.Connection, watching map[string]uint32, cmdLines []CmdLine) redis.Reply {
|
||||||
if conn.GetDBIndex() >= len(mdb.dbSet) {
|
if conn.GetDBIndex() >= len(mdb.dbSet) {
|
||||||
return reply.MakeErrReply("ERR DB index is out of range")
|
return protocol.MakeErrReply("ERR DB index is out of range")
|
||||||
}
|
}
|
||||||
db := mdb.dbSet[conn.GetDBIndex()]
|
db := mdb.dbSet[conn.GetDBIndex()]
|
||||||
return db.ExecMulti(conn, watching, cmdLines)
|
return db.ExecMulti(conn, watching, cmdLines)
|
||||||
@@ -215,11 +215,11 @@ func (mdb *MultiDB) ExecWithLock(conn redis.Connection, cmdLine [][]byte) redis.
|
|||||||
// BGRewriteAOF asynchronously rewrites Append-Only-File
|
// BGRewriteAOF asynchronously rewrites Append-Only-File
|
||||||
func BGRewriteAOF(db *MultiDB, args [][]byte) redis.Reply {
|
func BGRewriteAOF(db *MultiDB, args [][]byte) redis.Reply {
|
||||||
go db.aofHandler.Rewrite()
|
go db.aofHandler.Rewrite()
|
||||||
return reply.MakeStatusReply("Background append only file rewriting started")
|
return protocol.MakeStatusReply("Background append only file rewriting started")
|
||||||
}
|
}
|
||||||
|
|
||||||
// RewriteAOF start Append-Only-File rewriting and blocked until it finished
|
// RewriteAOF start Append-Only-File rewriting and blocked until it finished
|
||||||
func RewriteAOF(db *MultiDB, args [][]byte) redis.Reply {
|
func RewriteAOF(db *MultiDB, args [][]byte) redis.Reply {
|
||||||
db.aofHandler.Rewrite()
|
db.aofHandler.Rewrite()
|
||||||
return reply.MakeStatusReply("Background append only file rewriting started")
|
return protocol.MakeStatusReply("Background append only file rewriting started")
|
||||||
}
|
}
|
||||||
|
@@ -5,23 +5,23 @@ import (
|
|||||||
"github.com/hdt3213/godis/interface/database"
|
"github.com/hdt3213/godis/interface/database"
|
||||||
"github.com/hdt3213/godis/interface/redis"
|
"github.com/hdt3213/godis/interface/redis"
|
||||||
"github.com/hdt3213/godis/lib/utils"
|
"github.com/hdt3213/godis/lib/utils"
|
||||||
"github.com/hdt3213/godis/redis/reply"
|
"github.com/hdt3213/godis/redis/protocol"
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (db *DB) getAsSet(key string) (*HashSet.Set, reply.ErrorReply) {
|
func (db *DB) getAsSet(key string) (*HashSet.Set, protocol.ErrorReply) {
|
||||||
entity, exists := db.GetEntity(key)
|
entity, exists := db.GetEntity(key)
|
||||||
if !exists {
|
if !exists {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
set, ok := entity.Data.(*HashSet.Set)
|
set, ok := entity.Data.(*HashSet.Set)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, &reply.WrongTypeErrReply{}
|
return nil, &protocol.WrongTypeErrReply{}
|
||||||
}
|
}
|
||||||
return set, nil
|
return set, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) getOrInitSet(key string) (set *HashSet.Set, inited bool, errReply reply.ErrorReply) {
|
func (db *DB) getOrInitSet(key string) (set *HashSet.Set, inited bool, errReply protocol.ErrorReply) {
|
||||||
set, errReply = db.getAsSet(key)
|
set, errReply = db.getAsSet(key)
|
||||||
if errReply != nil {
|
if errReply != nil {
|
||||||
return nil, false, errReply
|
return nil, false, errReply
|
||||||
@@ -52,7 +52,7 @@ func execSAdd(db *DB, args [][]byte) redis.Reply {
|
|||||||
counter += set.Add(string(member))
|
counter += set.Add(string(member))
|
||||||
}
|
}
|
||||||
db.addAof(utils.ToCmdLine3("sadd", args...))
|
db.addAof(utils.ToCmdLine3("sadd", args...))
|
||||||
return reply.MakeIntReply(int64(counter))
|
return protocol.MakeIntReply(int64(counter))
|
||||||
}
|
}
|
||||||
|
|
||||||
// execSIsMember checks if the given value is member of set
|
// execSIsMember checks if the given value is member of set
|
||||||
@@ -66,14 +66,14 @@ func execSIsMember(db *DB, args [][]byte) redis.Reply {
|
|||||||
return errReply
|
return errReply
|
||||||
}
|
}
|
||||||
if set == nil {
|
if set == nil {
|
||||||
return reply.MakeIntReply(0)
|
return protocol.MakeIntReply(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
has := set.Has(member)
|
has := set.Has(member)
|
||||||
if has {
|
if has {
|
||||||
return reply.MakeIntReply(1)
|
return protocol.MakeIntReply(1)
|
||||||
}
|
}
|
||||||
return reply.MakeIntReply(0)
|
return protocol.MakeIntReply(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// execSRem removes a member from set
|
// execSRem removes a member from set
|
||||||
@@ -86,7 +86,7 @@ func execSRem(db *DB, args [][]byte) redis.Reply {
|
|||||||
return errReply
|
return errReply
|
||||||
}
|
}
|
||||||
if set == nil {
|
if set == nil {
|
||||||
return reply.MakeIntReply(0)
|
return protocol.MakeIntReply(0)
|
||||||
}
|
}
|
||||||
counter := 0
|
counter := 0
|
||||||
for _, member := range members {
|
for _, member := range members {
|
||||||
@@ -98,7 +98,7 @@ func execSRem(db *DB, args [][]byte) redis.Reply {
|
|||||||
if counter > 0 {
|
if counter > 0 {
|
||||||
db.addAof(utils.ToCmdLine3("srem", args...))
|
db.addAof(utils.ToCmdLine3("srem", args...))
|
||||||
}
|
}
|
||||||
return reply.MakeIntReply(int64(counter))
|
return protocol.MakeIntReply(int64(counter))
|
||||||
}
|
}
|
||||||
|
|
||||||
// execSCard gets the number of members in a set
|
// execSCard gets the number of members in a set
|
||||||
@@ -111,9 +111,9 @@ func execSCard(db *DB, args [][]byte) redis.Reply {
|
|||||||
return errReply
|
return errReply
|
||||||
}
|
}
|
||||||
if set == nil {
|
if set == nil {
|
||||||
return reply.MakeIntReply(0)
|
return protocol.MakeIntReply(0)
|
||||||
}
|
}
|
||||||
return reply.MakeIntReply(int64(set.Len()))
|
return protocol.MakeIntReply(int64(set.Len()))
|
||||||
}
|
}
|
||||||
|
|
||||||
// execSMembers gets all members in a set
|
// execSMembers gets all members in a set
|
||||||
@@ -126,7 +126,7 @@ func execSMembers(db *DB, args [][]byte) redis.Reply {
|
|||||||
return errReply
|
return errReply
|
||||||
}
|
}
|
||||||
if set == nil {
|
if set == nil {
|
||||||
return &reply.EmptyMultiBulkReply{}
|
return &protocol.EmptyMultiBulkReply{}
|
||||||
}
|
}
|
||||||
|
|
||||||
arr := make([][]byte, set.Len())
|
arr := make([][]byte, set.Len())
|
||||||
@@ -136,7 +136,7 @@ func execSMembers(db *DB, args [][]byte) redis.Reply {
|
|||||||
i++
|
i++
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
return reply.MakeMultiBulkReply(arr)
|
return protocol.MakeMultiBulkReply(arr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// execSInter intersect multiple sets
|
// execSInter intersect multiple sets
|
||||||
@@ -153,7 +153,7 @@ func execSInter(db *DB, args [][]byte) redis.Reply {
|
|||||||
return errReply
|
return errReply
|
||||||
}
|
}
|
||||||
if set == nil {
|
if set == nil {
|
||||||
return &reply.EmptyMultiBulkReply{}
|
return &protocol.EmptyMultiBulkReply{}
|
||||||
}
|
}
|
||||||
|
|
||||||
if result == nil {
|
if result == nil {
|
||||||
@@ -163,7 +163,7 @@ func execSInter(db *DB, args [][]byte) redis.Reply {
|
|||||||
result = result.Intersect(set)
|
result = result.Intersect(set)
|
||||||
if result.Len() == 0 {
|
if result.Len() == 0 {
|
||||||
// early termination
|
// early termination
|
||||||
return &reply.EmptyMultiBulkReply{}
|
return &protocol.EmptyMultiBulkReply{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -175,7 +175,7 @@ func execSInter(db *DB, args [][]byte) redis.Reply {
|
|||||||
i++
|
i++
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
return reply.MakeMultiBulkReply(arr)
|
return protocol.MakeMultiBulkReply(arr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// execSInterStore intersects multiple sets and store the result in a key
|
// execSInterStore intersects multiple sets and store the result in a key
|
||||||
@@ -195,7 +195,7 @@ func execSInterStore(db *DB, args [][]byte) redis.Reply {
|
|||||||
}
|
}
|
||||||
if set == nil {
|
if set == nil {
|
||||||
db.Remove(dest) // clean ttl and old value
|
db.Remove(dest) // clean ttl and old value
|
||||||
return reply.MakeIntReply(0)
|
return protocol.MakeIntReply(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
if result == nil {
|
if result == nil {
|
||||||
@@ -206,7 +206,7 @@ func execSInterStore(db *DB, args [][]byte) redis.Reply {
|
|||||||
if result.Len() == 0 {
|
if result.Len() == 0 {
|
||||||
// early termination
|
// early termination
|
||||||
db.Remove(dest) // clean ttl and old value
|
db.Remove(dest) // clean ttl and old value
|
||||||
return reply.MakeIntReply(0)
|
return protocol.MakeIntReply(0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -216,7 +216,7 @@ func execSInterStore(db *DB, args [][]byte) redis.Reply {
|
|||||||
Data: set,
|
Data: set,
|
||||||
})
|
})
|
||||||
db.addAof(utils.ToCmdLine3("sinterstore", args...))
|
db.addAof(utils.ToCmdLine3("sinterstore", args...))
|
||||||
return reply.MakeIntReply(int64(set.Len()))
|
return protocol.MakeIntReply(int64(set.Len()))
|
||||||
}
|
}
|
||||||
|
|
||||||
// execSUnion adds multiple sets
|
// execSUnion adds multiple sets
|
||||||
@@ -246,7 +246,7 @@ func execSUnion(db *DB, args [][]byte) redis.Reply {
|
|||||||
|
|
||||||
if result == nil {
|
if result == nil {
|
||||||
// all keys are empty set
|
// all keys are empty set
|
||||||
return &reply.EmptyMultiBulkReply{}
|
return &protocol.EmptyMultiBulkReply{}
|
||||||
}
|
}
|
||||||
arr := make([][]byte, result.Len())
|
arr := make([][]byte, result.Len())
|
||||||
i := 0
|
i := 0
|
||||||
@@ -255,7 +255,7 @@ func execSUnion(db *DB, args [][]byte) redis.Reply {
|
|||||||
i++
|
i++
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
return reply.MakeMultiBulkReply(arr)
|
return protocol.MakeMultiBulkReply(arr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// execSUnionStore adds multiple sets and store the result in a key
|
// execSUnionStore adds multiple sets and store the result in a key
|
||||||
@@ -287,7 +287,7 @@ func execSUnionStore(db *DB, args [][]byte) redis.Reply {
|
|||||||
db.Remove(dest) // clean ttl
|
db.Remove(dest) // clean ttl
|
||||||
if result == nil {
|
if result == nil {
|
||||||
// all keys are empty set
|
// all keys are empty set
|
||||||
return &reply.EmptyMultiBulkReply{}
|
return &protocol.EmptyMultiBulkReply{}
|
||||||
}
|
}
|
||||||
|
|
||||||
set := HashSet.Make(result.ToSlice()...)
|
set := HashSet.Make(result.ToSlice()...)
|
||||||
@@ -296,7 +296,7 @@ func execSUnionStore(db *DB, args [][]byte) redis.Reply {
|
|||||||
})
|
})
|
||||||
|
|
||||||
db.addAof(utils.ToCmdLine3("sunionstore", args...))
|
db.addAof(utils.ToCmdLine3("sunionstore", args...))
|
||||||
return reply.MakeIntReply(int64(set.Len()))
|
return protocol.MakeIntReply(int64(set.Len()))
|
||||||
}
|
}
|
||||||
|
|
||||||
// execSDiff subtracts multiple sets
|
// execSDiff subtracts multiple sets
|
||||||
@@ -315,7 +315,7 @@ func execSDiff(db *DB, args [][]byte) redis.Reply {
|
|||||||
if set == nil {
|
if set == nil {
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
// early termination
|
// early termination
|
||||||
return &reply.EmptyMultiBulkReply{}
|
return &protocol.EmptyMultiBulkReply{}
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -326,14 +326,14 @@ func execSDiff(db *DB, args [][]byte) redis.Reply {
|
|||||||
result = result.Diff(set)
|
result = result.Diff(set)
|
||||||
if result.Len() == 0 {
|
if result.Len() == 0 {
|
||||||
// early termination
|
// early termination
|
||||||
return &reply.EmptyMultiBulkReply{}
|
return &protocol.EmptyMultiBulkReply{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if result == nil {
|
if result == nil {
|
||||||
// all keys are nil
|
// all keys are nil
|
||||||
return &reply.EmptyMultiBulkReply{}
|
return &protocol.EmptyMultiBulkReply{}
|
||||||
}
|
}
|
||||||
arr := make([][]byte, result.Len())
|
arr := make([][]byte, result.Len())
|
||||||
i := 0
|
i := 0
|
||||||
@@ -342,7 +342,7 @@ func execSDiff(db *DB, args [][]byte) redis.Reply {
|
|||||||
i++
|
i++
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
return reply.MakeMultiBulkReply(arr)
|
return protocol.MakeMultiBulkReply(arr)
|
||||||
}
|
}
|
||||||
|
|
||||||
// execSDiffStore subtracts multiple sets and store the result in a key
|
// execSDiffStore subtracts multiple sets and store the result in a key
|
||||||
@@ -364,7 +364,7 @@ func execSDiffStore(db *DB, args [][]byte) redis.Reply {
|
|||||||
if i == 0 {
|
if i == 0 {
|
||||||
// early termination
|
// early termination
|
||||||
db.Remove(dest)
|
db.Remove(dest)
|
||||||
return reply.MakeIntReply(0)
|
return protocol.MakeIntReply(0)
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -376,7 +376,7 @@ func execSDiffStore(db *DB, args [][]byte) redis.Reply {
|
|||||||
if result.Len() == 0 {
|
if result.Len() == 0 {
|
||||||
// early termination
|
// early termination
|
||||||
db.Remove(dest)
|
db.Remove(dest)
|
||||||
return reply.MakeIntReply(0)
|
return protocol.MakeIntReply(0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -384,7 +384,7 @@ func execSDiffStore(db *DB, args [][]byte) redis.Reply {
|
|||||||
if result == nil {
|
if result == nil {
|
||||||
// all keys are nil
|
// all keys are nil
|
||||||
db.Remove(dest)
|
db.Remove(dest)
|
||||||
return &reply.EmptyMultiBulkReply{}
|
return &protocol.EmptyMultiBulkReply{}
|
||||||
}
|
}
|
||||||
set := HashSet.Make(result.ToSlice()...)
|
set := HashSet.Make(result.ToSlice()...)
|
||||||
db.PutEntity(dest, &database.DataEntity{
|
db.PutEntity(dest, &database.DataEntity{
|
||||||
@@ -392,13 +392,13 @@ func execSDiffStore(db *DB, args [][]byte) redis.Reply {
|
|||||||
})
|
})
|
||||||
|
|
||||||
db.addAof(utils.ToCmdLine3("sdiffstore", args...))
|
db.addAof(utils.ToCmdLine3("sdiffstore", args...))
|
||||||
return reply.MakeIntReply(int64(set.Len()))
|
return protocol.MakeIntReply(int64(set.Len()))
|
||||||
}
|
}
|
||||||
|
|
||||||
// execSRandMember gets random members from set
|
// execSRandMember gets random members from set
|
||||||
func execSRandMember(db *DB, args [][]byte) redis.Reply {
|
func execSRandMember(db *DB, args [][]byte) redis.Reply {
|
||||||
if len(args) != 1 && len(args) != 2 {
|
if len(args) != 1 && len(args) != 2 {
|
||||||
return reply.MakeErrReply("ERR wrong number of arguments for 'srandmember' command")
|
return protocol.MakeErrReply("ERR wrong number of arguments for 'srandmember' command")
|
||||||
}
|
}
|
||||||
key := string(args[0])
|
key := string(args[0])
|
||||||
|
|
||||||
@@ -408,16 +408,16 @@ func execSRandMember(db *DB, args [][]byte) redis.Reply {
|
|||||||
return errReply
|
return errReply
|
||||||
}
|
}
|
||||||
if set == nil {
|
if set == nil {
|
||||||
return &reply.NullBulkReply{}
|
return &protocol.NullBulkReply{}
|
||||||
}
|
}
|
||||||
if len(args) == 1 {
|
if len(args) == 1 {
|
||||||
// get a random member
|
// get a random member
|
||||||
members := set.RandomMembers(1)
|
members := set.RandomMembers(1)
|
||||||
return reply.MakeBulkReply([]byte(members[0]))
|
return protocol.MakeBulkReply([]byte(members[0]))
|
||||||
}
|
}
|
||||||
count64, err := strconv.ParseInt(string(args[1]), 10, 64)
|
count64, err := strconv.ParseInt(string(args[1]), 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reply.MakeErrReply("ERR value is not an integer or out of range")
|
return protocol.MakeErrReply("ERR value is not an integer or out of range")
|
||||||
}
|
}
|
||||||
count := int(count64)
|
count := int(count64)
|
||||||
if count > 0 {
|
if count > 0 {
|
||||||
@@ -426,16 +426,16 @@ func execSRandMember(db *DB, args [][]byte) redis.Reply {
|
|||||||
for i, v := range members {
|
for i, v := range members {
|
||||||
result[i] = []byte(v)
|
result[i] = []byte(v)
|
||||||
}
|
}
|
||||||
return reply.MakeMultiBulkReply(result)
|
return protocol.MakeMultiBulkReply(result)
|
||||||
} else if count < 0 {
|
} else if count < 0 {
|
||||||
members := set.RandomMembers(-count)
|
members := set.RandomMembers(-count)
|
||||||
result := make([][]byte, len(members))
|
result := make([][]byte, len(members))
|
||||||
for i, v := range members {
|
for i, v := range members {
|
||||||
result[i] = []byte(v)
|
result[i] = []byte(v)
|
||||||
}
|
}
|
||||||
return reply.MakeMultiBulkReply(result)
|
return protocol.MakeMultiBulkReply(result)
|
||||||
}
|
}
|
||||||
return &reply.EmptyMultiBulkReply{}
|
return &protocol.EmptyMultiBulkReply{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@@ -3,8 +3,8 @@ package database
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/hdt3213/godis/lib/utils"
|
"github.com/hdt3213/godis/lib/utils"
|
||||||
"github.com/hdt3213/godis/redis/reply"
|
"github.com/hdt3213/godis/redis/protocol"
|
||||||
"github.com/hdt3213/godis/redis/reply/asserts"
|
"github.com/hdt3213/godis/redis/protocol/asserts"
|
||||||
"strconv"
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
@@ -34,9 +34,9 @@ func TestSAdd(t *testing.T) {
|
|||||||
|
|
||||||
// test members
|
// test members
|
||||||
result = testDB.Exec(nil, utils.ToCmdLine("SMembers", key))
|
result = testDB.Exec(nil, utils.ToCmdLine("SMembers", key))
|
||||||
multiBulk, ok := result.(*reply.MultiBulkReply)
|
multiBulk, ok := result.(*protocol.MultiBulkReply)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Error(fmt.Sprintf("expected bulk reply, actually %s", result.ToBytes()))
|
t.Error(fmt.Sprintf("expected bulk protocol, actually %s", result.ToBytes()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if len(multiBulk.Args) != size {
|
if len(multiBulk.Args) != size {
|
||||||
@@ -183,17 +183,17 @@ func TestSRandMember(t *testing.T) {
|
|||||||
testDB.Exec(nil, utils.ToCmdLine("sadd", key, member))
|
testDB.Exec(nil, utils.ToCmdLine("sadd", key, member))
|
||||||
}
|
}
|
||||||
result := testDB.Exec(nil, utils.ToCmdLine("SRandMember", key))
|
result := testDB.Exec(nil, utils.ToCmdLine("SRandMember", key))
|
||||||
br, ok := result.(*reply.BulkReply)
|
br, ok := result.(*protocol.BulkReply)
|
||||||
if !ok && len(br.Arg) > 0 {
|
if !ok && len(br.Arg) > 0 {
|
||||||
t.Error(fmt.Sprintf("expected bulk reply, actually %s", result.ToBytes()))
|
t.Error(fmt.Sprintf("expected bulk protocol, actually %s", result.ToBytes()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
result = testDB.Exec(nil, utils.ToCmdLine("SRandMember", key, "10"))
|
result = testDB.Exec(nil, utils.ToCmdLine("SRandMember", key, "10"))
|
||||||
asserts.AssertMultiBulkReplySize(t, result, 10)
|
asserts.AssertMultiBulkReplySize(t, result, 10)
|
||||||
multiBulk, ok := result.(*reply.MultiBulkReply)
|
multiBulk, ok := result.(*protocol.MultiBulkReply)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Error(fmt.Sprintf("expected bulk reply, actually %s", result.ToBytes()))
|
t.Error(fmt.Sprintf("expected bulk protocol, actually %s", result.ToBytes()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
m := make(map[string]struct{})
|
m := make(map[string]struct{})
|
||||||
|
@@ -5,24 +5,24 @@ import (
|
|||||||
"github.com/hdt3213/godis/interface/database"
|
"github.com/hdt3213/godis/interface/database"
|
||||||
"github.com/hdt3213/godis/interface/redis"
|
"github.com/hdt3213/godis/interface/redis"
|
||||||
"github.com/hdt3213/godis/lib/utils"
|
"github.com/hdt3213/godis/lib/utils"
|
||||||
"github.com/hdt3213/godis/redis/reply"
|
"github.com/hdt3213/godis/redis/protocol"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (db *DB) getAsSortedSet(key string) (*SortedSet.SortedSet, reply.ErrorReply) {
|
func (db *DB) getAsSortedSet(key string) (*SortedSet.SortedSet, protocol.ErrorReply) {
|
||||||
entity, exists := db.GetEntity(key)
|
entity, exists := db.GetEntity(key)
|
||||||
if !exists {
|
if !exists {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
sortedSet, ok := entity.Data.(*SortedSet.SortedSet)
|
sortedSet, ok := entity.Data.(*SortedSet.SortedSet)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, &reply.WrongTypeErrReply{}
|
return nil, &protocol.WrongTypeErrReply{}
|
||||||
}
|
}
|
||||||
return sortedSet, nil
|
return sortedSet, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *DB) getOrInitSortedSet(key string) (sortedSet *SortedSet.SortedSet, inited bool, errReply reply.ErrorReply) {
|
func (db *DB) getOrInitSortedSet(key string) (sortedSet *SortedSet.SortedSet, inited bool, errReply protocol.ErrorReply) {
|
||||||
sortedSet, errReply = db.getAsSortedSet(key)
|
sortedSet, errReply = db.getAsSortedSet(key)
|
||||||
if errReply != nil {
|
if errReply != nil {
|
||||||
return nil, false, errReply
|
return nil, false, errReply
|
||||||
@@ -41,7 +41,7 @@ func (db *DB) getOrInitSortedSet(key string) (sortedSet *SortedSet.SortedSet, in
|
|||||||
// execZAdd adds member into sorted set
|
// execZAdd adds member into sorted set
|
||||||
func execZAdd(db *DB, args [][]byte) redis.Reply {
|
func execZAdd(db *DB, args [][]byte) redis.Reply {
|
||||||
if len(args)%2 != 1 {
|
if len(args)%2 != 1 {
|
||||||
return reply.MakeSyntaxErrReply()
|
return protocol.MakeSyntaxErrReply()
|
||||||
}
|
}
|
||||||
key := string(args[0])
|
key := string(args[0])
|
||||||
size := (len(args) - 1) / 2
|
size := (len(args) - 1) / 2
|
||||||
@@ -51,7 +51,7 @@ func execZAdd(db *DB, args [][]byte) redis.Reply {
|
|||||||
member := string(args[2*i+2])
|
member := string(args[2*i+2])
|
||||||
score, err := strconv.ParseFloat(string(scoreValue), 64)
|
score, err := strconv.ParseFloat(string(scoreValue), 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reply.MakeErrReply("ERR value is not a valid float")
|
return protocol.MakeErrReply("ERR value is not a valid float")
|
||||||
}
|
}
|
||||||
elements[i] = &SortedSet.Element{
|
elements[i] = &SortedSet.Element{
|
||||||
Member: member,
|
Member: member,
|
||||||
@@ -74,7 +74,7 @@ func execZAdd(db *DB, args [][]byte) redis.Reply {
|
|||||||
|
|
||||||
db.addAof(utils.ToCmdLine3("zadd", args...))
|
db.addAof(utils.ToCmdLine3("zadd", args...))
|
||||||
|
|
||||||
return reply.MakeIntReply(int64(i))
|
return protocol.MakeIntReply(int64(i))
|
||||||
}
|
}
|
||||||
|
|
||||||
func undoZAdd(db *DB, args [][]byte) []CmdLine {
|
func undoZAdd(db *DB, args [][]byte) []CmdLine {
|
||||||
@@ -98,15 +98,15 @@ func execZScore(db *DB, args [][]byte) redis.Reply {
|
|||||||
return errReply
|
return errReply
|
||||||
}
|
}
|
||||||
if sortedSet == nil {
|
if sortedSet == nil {
|
||||||
return &reply.NullBulkReply{}
|
return &protocol.NullBulkReply{}
|
||||||
}
|
}
|
||||||
|
|
||||||
element, exists := sortedSet.Get(member)
|
element, exists := sortedSet.Get(member)
|
||||||
if !exists {
|
if !exists {
|
||||||
return &reply.NullBulkReply{}
|
return &protocol.NullBulkReply{}
|
||||||
}
|
}
|
||||||
value := strconv.FormatFloat(element.Score, 'f', -1, 64)
|
value := strconv.FormatFloat(element.Score, 'f', -1, 64)
|
||||||
return reply.MakeBulkReply([]byte(value))
|
return protocol.MakeBulkReply([]byte(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
// execZRank gets index of a member in sortedset, ascending order, start from 0
|
// execZRank gets index of a member in sortedset, ascending order, start from 0
|
||||||
@@ -121,14 +121,14 @@ func execZRank(db *DB, args [][]byte) redis.Reply {
|
|||||||
return errReply
|
return errReply
|
||||||
}
|
}
|
||||||
if sortedSet == nil {
|
if sortedSet == nil {
|
||||||
return &reply.NullBulkReply{}
|
return &protocol.NullBulkReply{}
|
||||||
}
|
}
|
||||||
|
|
||||||
rank := sortedSet.GetRank(member, false)
|
rank := sortedSet.GetRank(member, false)
|
||||||
if rank < 0 {
|
if rank < 0 {
|
||||||
return &reply.NullBulkReply{}
|
return &protocol.NullBulkReply{}
|
||||||
}
|
}
|
||||||
return reply.MakeIntReply(rank)
|
return protocol.MakeIntReply(rank)
|
||||||
}
|
}
|
||||||
|
|
||||||
// execZRevRank gets index of a member in sortedset, descending order, start from 0
|
// execZRevRank gets index of a member in sortedset, descending order, start from 0
|
||||||
@@ -143,14 +143,14 @@ func execZRevRank(db *DB, args [][]byte) redis.Reply {
|
|||||||
return errReply
|
return errReply
|
||||||
}
|
}
|
||||||
if sortedSet == nil {
|
if sortedSet == nil {
|
||||||
return &reply.NullBulkReply{}
|
return &protocol.NullBulkReply{}
|
||||||
}
|
}
|
||||||
|
|
||||||
rank := sortedSet.GetRank(member, true)
|
rank := sortedSet.GetRank(member, true)
|
||||||
if rank < 0 {
|
if rank < 0 {
|
||||||
return &reply.NullBulkReply{}
|
return &protocol.NullBulkReply{}
|
||||||
}
|
}
|
||||||
return reply.MakeIntReply(rank)
|
return protocol.MakeIntReply(rank)
|
||||||
}
|
}
|
||||||
|
|
||||||
// execZCard gets number of members in sortedset
|
// execZCard gets number of members in sortedset
|
||||||
@@ -164,33 +164,33 @@ func execZCard(db *DB, args [][]byte) redis.Reply {
|
|||||||
return errReply
|
return errReply
|
||||||
}
|
}
|
||||||
if sortedSet == nil {
|
if sortedSet == nil {
|
||||||
return reply.MakeIntReply(0)
|
return protocol.MakeIntReply(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
return reply.MakeIntReply(sortedSet.Len())
|
return protocol.MakeIntReply(sortedSet.Len())
|
||||||
}
|
}
|
||||||
|
|
||||||
// execZRange gets members in range, sort by score in ascending order
|
// execZRange gets members in range, sort by score in ascending order
|
||||||
func execZRange(db *DB, args [][]byte) redis.Reply {
|
func execZRange(db *DB, args [][]byte) redis.Reply {
|
||||||
// parse args
|
// parse args
|
||||||
if len(args) != 3 && len(args) != 4 {
|
if len(args) != 3 && len(args) != 4 {
|
||||||
return reply.MakeErrReply("ERR wrong number of arguments for 'zrange' command")
|
return protocol.MakeErrReply("ERR wrong number of arguments for 'zrange' command")
|
||||||
}
|
}
|
||||||
withScores := false
|
withScores := false
|
||||||
if len(args) == 4 {
|
if len(args) == 4 {
|
||||||
if strings.ToUpper(string(args[3])) != "WITHSCORES" {
|
if strings.ToUpper(string(args[3])) != "WITHSCORES" {
|
||||||
return reply.MakeErrReply("syntax error")
|
return protocol.MakeErrReply("syntax error")
|
||||||
}
|
}
|
||||||
withScores = true
|
withScores = true
|
||||||
}
|
}
|
||||||
key := string(args[0])
|
key := string(args[0])
|
||||||
start, err := strconv.ParseInt(string(args[1]), 10, 64)
|
start, err := strconv.ParseInt(string(args[1]), 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reply.MakeErrReply("ERR value is not an integer or out of range")
|
return protocol.MakeErrReply("ERR value is not an integer or out of range")
|
||||||
}
|
}
|
||||||
stop, err := strconv.ParseInt(string(args[2]), 10, 64)
|
stop, err := strconv.ParseInt(string(args[2]), 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reply.MakeErrReply("ERR value is not an integer or out of range")
|
return protocol.MakeErrReply("ERR value is not an integer or out of range")
|
||||||
}
|
}
|
||||||
return range0(db, key, start, stop, withScores, false)
|
return range0(db, key, start, stop, withScores, false)
|
||||||
}
|
}
|
||||||
@@ -199,23 +199,23 @@ func execZRange(db *DB, args [][]byte) redis.Reply {
|
|||||||
func execZRevRange(db *DB, args [][]byte) redis.Reply {
|
func execZRevRange(db *DB, args [][]byte) redis.Reply {
|
||||||
// parse args
|
// parse args
|
||||||
if len(args) != 3 && len(args) != 4 {
|
if len(args) != 3 && len(args) != 4 {
|
||||||
return reply.MakeErrReply("ERR wrong number of arguments for 'zrevrange' command")
|
return protocol.MakeErrReply("ERR wrong number of arguments for 'zrevrange' command")
|
||||||
}
|
}
|
||||||
withScores := false
|
withScores := false
|
||||||
if len(args) == 4 {
|
if len(args) == 4 {
|
||||||
if string(args[3]) != "WITHSCORES" {
|
if string(args[3]) != "WITHSCORES" {
|
||||||
return reply.MakeErrReply("syntax error")
|
return protocol.MakeErrReply("syntax error")
|
||||||
}
|
}
|
||||||
withScores = true
|
withScores = true
|
||||||
}
|
}
|
||||||
key := string(args[0])
|
key := string(args[0])
|
||||||
start, err := strconv.ParseInt(string(args[1]), 10, 64)
|
start, err := strconv.ParseInt(string(args[1]), 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reply.MakeErrReply("ERR value is not an integer or out of range")
|
return protocol.MakeErrReply("ERR value is not an integer or out of range")
|
||||||
}
|
}
|
||||||
stop, err := strconv.ParseInt(string(args[2]), 10, 64)
|
stop, err := strconv.ParseInt(string(args[2]), 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reply.MakeErrReply("ERR value is not an integer or out of range")
|
return protocol.MakeErrReply("ERR value is not an integer or out of range")
|
||||||
}
|
}
|
||||||
return range0(db, key, start, stop, withScores, true)
|
return range0(db, key, start, stop, withScores, true)
|
||||||
}
|
}
|
||||||
@@ -227,7 +227,7 @@ func range0(db *DB, key string, start int64, stop int64, withScores bool, desc b
|
|||||||
return errReply
|
return errReply
|
||||||
}
|
}
|
||||||
if sortedSet == nil {
|
if sortedSet == nil {
|
||||||
return &reply.EmptyMultiBulkReply{}
|
return &protocol.EmptyMultiBulkReply{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// compute index
|
// compute index
|
||||||
@@ -237,7 +237,7 @@ func range0(db *DB, key string, start int64, stop int64, withScores bool, desc b
|
|||||||
} else if start < 0 {
|
} else if start < 0 {
|
||||||
start = size + start
|
start = size + start
|
||||||
} else if start >= size {
|
} else if start >= size {
|
||||||
return &reply.EmptyMultiBulkReply{}
|
return &protocol.EmptyMultiBulkReply{}
|
||||||
}
|
}
|
||||||
if stop < -1*size {
|
if stop < -1*size {
|
||||||
stop = 0
|
stop = 0
|
||||||
@@ -264,7 +264,7 @@ func range0(db *DB, key string, start int64, stop int64, withScores bool, desc b
|
|||||||
result[i] = []byte(scoreStr)
|
result[i] = []byte(scoreStr)
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
return reply.MakeMultiBulkReply(result)
|
return protocol.MakeMultiBulkReply(result)
|
||||||
}
|
}
|
||||||
result := make([][]byte, len(slice))
|
result := make([][]byte, len(slice))
|
||||||
i := 0
|
i := 0
|
||||||
@@ -272,7 +272,7 @@ func range0(db *DB, key string, start int64, stop int64, withScores bool, desc b
|
|||||||
result[i] = []byte(element.Member)
|
result[i] = []byte(element.Member)
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
return reply.MakeMultiBulkReply(result)
|
return protocol.MakeMultiBulkReply(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
// execZCount gets number of members which score within given range
|
// execZCount gets number of members which score within given range
|
||||||
@@ -281,12 +281,12 @@ func execZCount(db *DB, args [][]byte) redis.Reply {
|
|||||||
|
|
||||||
min, err := SortedSet.ParseScoreBorder(string(args[1]))
|
min, err := SortedSet.ParseScoreBorder(string(args[1]))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reply.MakeErrReply(err.Error())
|
return protocol.MakeErrReply(err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
max, err := SortedSet.ParseScoreBorder(string(args[2]))
|
max, err := SortedSet.ParseScoreBorder(string(args[2]))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reply.MakeErrReply(err.Error())
|
return protocol.MakeErrReply(err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
// get data
|
// get data
|
||||||
@@ -295,10 +295,10 @@ func execZCount(db *DB, args [][]byte) redis.Reply {
|
|||||||
return errReply
|
return errReply
|
||||||
}
|
}
|
||||||
if sortedSet == nil {
|
if sortedSet == nil {
|
||||||
return reply.MakeIntReply(0)
|
return protocol.MakeIntReply(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
return reply.MakeIntReply(sortedSet.Count(min, max))
|
return protocol.MakeIntReply(sortedSet.Count(min, max))
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -311,7 +311,7 @@ func rangeByScore0(db *DB, key string, min *SortedSet.ScoreBorder, max *SortedSe
|
|||||||
return errReply
|
return errReply
|
||||||
}
|
}
|
||||||
if sortedSet == nil {
|
if sortedSet == nil {
|
||||||
return &reply.EmptyMultiBulkReply{}
|
return &protocol.EmptyMultiBulkReply{}
|
||||||
}
|
}
|
||||||
|
|
||||||
slice := sortedSet.RangeByScore(min, max, offset, limit, desc)
|
slice := sortedSet.RangeByScore(min, max, offset, limit, desc)
|
||||||
@@ -325,7 +325,7 @@ func rangeByScore0(db *DB, key string, min *SortedSet.ScoreBorder, max *SortedSe
|
|||||||
result[i] = []byte(scoreStr)
|
result[i] = []byte(scoreStr)
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
return reply.MakeMultiBulkReply(result)
|
return protocol.MakeMultiBulkReply(result)
|
||||||
}
|
}
|
||||||
result := make([][]byte, len(slice))
|
result := make([][]byte, len(slice))
|
||||||
i := 0
|
i := 0
|
||||||
@@ -333,24 +333,24 @@ func rangeByScore0(db *DB, key string, min *SortedSet.ScoreBorder, max *SortedSe
|
|||||||
result[i] = []byte(element.Member)
|
result[i] = []byte(element.Member)
|
||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
return reply.MakeMultiBulkReply(result)
|
return protocol.MakeMultiBulkReply(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
// execZRangeByScore gets members which score within given range, in ascending order
|
// execZRangeByScore gets members which score within given range, in ascending order
|
||||||
func execZRangeByScore(db *DB, args [][]byte) redis.Reply {
|
func execZRangeByScore(db *DB, args [][]byte) redis.Reply {
|
||||||
if len(args) < 3 {
|
if len(args) < 3 {
|
||||||
return reply.MakeErrReply("ERR wrong number of arguments for 'zrangebyscore' command")
|
return protocol.MakeErrReply("ERR wrong number of arguments for 'zrangebyscore' command")
|
||||||
}
|
}
|
||||||
key := string(args[0])
|
key := string(args[0])
|
||||||
|
|
||||||
min, err := SortedSet.ParseScoreBorder(string(args[1]))
|
min, err := SortedSet.ParseScoreBorder(string(args[1]))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reply.MakeErrReply(err.Error())
|
return protocol.MakeErrReply(err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
max, err := SortedSet.ParseScoreBorder(string(args[2]))
|
max, err := SortedSet.ParseScoreBorder(string(args[2]))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reply.MakeErrReply(err.Error())
|
return protocol.MakeErrReply(err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
withScores := false
|
withScores := false
|
||||||
@@ -364,19 +364,19 @@ func execZRangeByScore(db *DB, args [][]byte) redis.Reply {
|
|||||||
i++
|
i++
|
||||||
} else if strings.ToUpper(s) == "LIMIT" {
|
} else if strings.ToUpper(s) == "LIMIT" {
|
||||||
if len(args) < i+3 {
|
if len(args) < i+3 {
|
||||||
return reply.MakeErrReply("ERR syntax error")
|
return protocol.MakeErrReply("ERR syntax error")
|
||||||
}
|
}
|
||||||
offset, err = strconv.ParseInt(string(args[i+1]), 10, 64)
|
offset, err = strconv.ParseInt(string(args[i+1]), 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reply.MakeErrReply("ERR value is not an integer or out of range")
|
return protocol.MakeErrReply("ERR value is not an integer or out of range")
|
||||||
}
|
}
|
||||||
limit, err = strconv.ParseInt(string(args[i+2]), 10, 64)
|
limit, err = strconv.ParseInt(string(args[i+2]), 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reply.MakeErrReply("ERR value is not an integer or out of range")
|
return protocol.MakeErrReply("ERR value is not an integer or out of range")
|
||||||
}
|
}
|
||||||
i += 3
|
i += 3
|
||||||
} else {
|
} else {
|
||||||
return reply.MakeErrReply("ERR syntax error")
|
return protocol.MakeErrReply("ERR syntax error")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -386,18 +386,18 @@ func execZRangeByScore(db *DB, args [][]byte) redis.Reply {
|
|||||||
// execZRevRangeByScore gets number of members which score within given range, in descending order
|
// execZRevRangeByScore gets number of members which score within given range, in descending order
|
||||||
func execZRevRangeByScore(db *DB, args [][]byte) redis.Reply {
|
func execZRevRangeByScore(db *DB, args [][]byte) redis.Reply {
|
||||||
if len(args) < 3 {
|
if len(args) < 3 {
|
||||||
return reply.MakeErrReply("ERR wrong number of arguments for 'zrangebyscore' command")
|
return protocol.MakeErrReply("ERR wrong number of arguments for 'zrangebyscore' command")
|
||||||
}
|
}
|
||||||
key := string(args[0])
|
key := string(args[0])
|
||||||
|
|
||||||
min, err := SortedSet.ParseScoreBorder(string(args[2]))
|
min, err := SortedSet.ParseScoreBorder(string(args[2]))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reply.MakeErrReply(err.Error())
|
return protocol.MakeErrReply(err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
max, err := SortedSet.ParseScoreBorder(string(args[1]))
|
max, err := SortedSet.ParseScoreBorder(string(args[1]))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reply.MakeErrReply(err.Error())
|
return protocol.MakeErrReply(err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
withScores := false
|
withScores := false
|
||||||
@@ -411,19 +411,19 @@ func execZRevRangeByScore(db *DB, args [][]byte) redis.Reply {
|
|||||||
i++
|
i++
|
||||||
} else if strings.ToUpper(s) == "LIMIT" {
|
} else if strings.ToUpper(s) == "LIMIT" {
|
||||||
if len(args) < i+3 {
|
if len(args) < i+3 {
|
||||||
return reply.MakeErrReply("ERR syntax error")
|
return protocol.MakeErrReply("ERR syntax error")
|
||||||
}
|
}
|
||||||
offset, err = strconv.ParseInt(string(args[i+1]), 10, 64)
|
offset, err = strconv.ParseInt(string(args[i+1]), 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reply.MakeErrReply("ERR value is not an integer or out of range")
|
return protocol.MakeErrReply("ERR value is not an integer or out of range")
|
||||||
}
|
}
|
||||||
limit, err = strconv.ParseInt(string(args[i+2]), 10, 64)
|
limit, err = strconv.ParseInt(string(args[i+2]), 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reply.MakeErrReply("ERR value is not an integer or out of range")
|
return protocol.MakeErrReply("ERR value is not an integer or out of range")
|
||||||
}
|
}
|
||||||
i += 3
|
i += 3
|
||||||
} else {
|
} else {
|
||||||
return reply.MakeErrReply("ERR syntax error")
|
return protocol.MakeErrReply("ERR syntax error")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -433,18 +433,18 @@ func execZRevRangeByScore(db *DB, args [][]byte) redis.Reply {
|
|||||||
// execZRemRangeByScore removes members which score within given range
|
// execZRemRangeByScore removes members which score within given range
|
||||||
func execZRemRangeByScore(db *DB, args [][]byte) redis.Reply {
|
func execZRemRangeByScore(db *DB, args [][]byte) redis.Reply {
|
||||||
if len(args) != 3 {
|
if len(args) != 3 {
|
||||||
return reply.MakeErrReply("ERR wrong number of arguments for 'zremrangebyscore' command")
|
return protocol.MakeErrReply("ERR wrong number of arguments for 'zremrangebyscore' command")
|
||||||
}
|
}
|
||||||
key := string(args[0])
|
key := string(args[0])
|
||||||
|
|
||||||
min, err := SortedSet.ParseScoreBorder(string(args[1]))
|
min, err := SortedSet.ParseScoreBorder(string(args[1]))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reply.MakeErrReply(err.Error())
|
return protocol.MakeErrReply(err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
max, err := SortedSet.ParseScoreBorder(string(args[2]))
|
max, err := SortedSet.ParseScoreBorder(string(args[2]))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reply.MakeErrReply(err.Error())
|
return protocol.MakeErrReply(err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
// get data
|
// get data
|
||||||
@@ -453,14 +453,14 @@ func execZRemRangeByScore(db *DB, args [][]byte) redis.Reply {
|
|||||||
return errReply
|
return errReply
|
||||||
}
|
}
|
||||||
if sortedSet == nil {
|
if sortedSet == nil {
|
||||||
return &reply.EmptyMultiBulkReply{}
|
return &protocol.EmptyMultiBulkReply{}
|
||||||
}
|
}
|
||||||
|
|
||||||
removed := sortedSet.RemoveByScore(min, max)
|
removed := sortedSet.RemoveByScore(min, max)
|
||||||
if removed > 0 {
|
if removed > 0 {
|
||||||
db.addAof(utils.ToCmdLine3("zremrangebyscore", args...))
|
db.addAof(utils.ToCmdLine3("zremrangebyscore", args...))
|
||||||
}
|
}
|
||||||
return reply.MakeIntReply(removed)
|
return protocol.MakeIntReply(removed)
|
||||||
}
|
}
|
||||||
|
|
||||||
// execZRemRangeByRank removes members within given indexes
|
// execZRemRangeByRank removes members within given indexes
|
||||||
@@ -468,11 +468,11 @@ func execZRemRangeByRank(db *DB, args [][]byte) redis.Reply {
|
|||||||
key := string(args[0])
|
key := string(args[0])
|
||||||
start, err := strconv.ParseInt(string(args[1]), 10, 64)
|
start, err := strconv.ParseInt(string(args[1]), 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reply.MakeErrReply("ERR value is not an integer or out of range")
|
return protocol.MakeErrReply("ERR value is not an integer or out of range")
|
||||||
}
|
}
|
||||||
stop, err := strconv.ParseInt(string(args[2]), 10, 64)
|
stop, err := strconv.ParseInt(string(args[2]), 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reply.MakeErrReply("ERR value is not an integer or out of range")
|
return protocol.MakeErrReply("ERR value is not an integer or out of range")
|
||||||
}
|
}
|
||||||
|
|
||||||
// get data
|
// get data
|
||||||
@@ -481,7 +481,7 @@ func execZRemRangeByRank(db *DB, args [][]byte) redis.Reply {
|
|||||||
return errReply
|
return errReply
|
||||||
}
|
}
|
||||||
if sortedSet == nil {
|
if sortedSet == nil {
|
||||||
return reply.MakeIntReply(0)
|
return protocol.MakeIntReply(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// compute index
|
// compute index
|
||||||
@@ -491,7 +491,7 @@ func execZRemRangeByRank(db *DB, args [][]byte) redis.Reply {
|
|||||||
} else if start < 0 {
|
} else if start < 0 {
|
||||||
start = size + start
|
start = size + start
|
||||||
} else if start >= size {
|
} else if start >= size {
|
||||||
return reply.MakeIntReply(0)
|
return protocol.MakeIntReply(0)
|
||||||
}
|
}
|
||||||
if stop < -1*size {
|
if stop < -1*size {
|
||||||
stop = 0
|
stop = 0
|
||||||
@@ -511,7 +511,7 @@ func execZRemRangeByRank(db *DB, args [][]byte) redis.Reply {
|
|||||||
if removed > 0 {
|
if removed > 0 {
|
||||||
db.addAof(utils.ToCmdLine3("zremrangebyrank", args...))
|
db.addAof(utils.ToCmdLine3("zremrangebyrank", args...))
|
||||||
}
|
}
|
||||||
return reply.MakeIntReply(removed)
|
return protocol.MakeIntReply(removed)
|
||||||
}
|
}
|
||||||
|
|
||||||
// execZRem removes given members
|
// execZRem removes given members
|
||||||
@@ -530,7 +530,7 @@ func execZRem(db *DB, args [][]byte) redis.Reply {
|
|||||||
return errReply
|
return errReply
|
||||||
}
|
}
|
||||||
if sortedSet == nil {
|
if sortedSet == nil {
|
||||||
return reply.MakeIntReply(0)
|
return protocol.MakeIntReply(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
var deleted int64 = 0
|
var deleted int64 = 0
|
||||||
@@ -542,7 +542,7 @@ func execZRem(db *DB, args [][]byte) redis.Reply {
|
|||||||
if deleted > 0 {
|
if deleted > 0 {
|
||||||
db.addAof(utils.ToCmdLine3("zrem", args...))
|
db.addAof(utils.ToCmdLine3("zrem", args...))
|
||||||
}
|
}
|
||||||
return reply.MakeIntReply(deleted)
|
return protocol.MakeIntReply(deleted)
|
||||||
}
|
}
|
||||||
|
|
||||||
func undoZRem(db *DB, args [][]byte) []CmdLine {
|
func undoZRem(db *DB, args [][]byte) []CmdLine {
|
||||||
@@ -562,7 +562,7 @@ func execZIncrBy(db *DB, args [][]byte) redis.Reply {
|
|||||||
field := string(args[2])
|
field := string(args[2])
|
||||||
delta, err := strconv.ParseFloat(rawDelta, 64)
|
delta, err := strconv.ParseFloat(rawDelta, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reply.MakeErrReply("ERR value is not a valid float")
|
return protocol.MakeErrReply("ERR value is not a valid float")
|
||||||
}
|
}
|
||||||
|
|
||||||
// get or init entity
|
// get or init entity
|
||||||
@@ -575,13 +575,13 @@ func execZIncrBy(db *DB, args [][]byte) redis.Reply {
|
|||||||
if !exists {
|
if !exists {
|
||||||
sortedSet.Add(field, delta)
|
sortedSet.Add(field, delta)
|
||||||
db.addAof(utils.ToCmdLine3("zincrby", args...))
|
db.addAof(utils.ToCmdLine3("zincrby", args...))
|
||||||
return reply.MakeBulkReply(args[1])
|
return protocol.MakeBulkReply(args[1])
|
||||||
}
|
}
|
||||||
score := element.Score + delta
|
score := element.Score + delta
|
||||||
sortedSet.Add(field, score)
|
sortedSet.Add(field, score)
|
||||||
bytes := []byte(strconv.FormatFloat(score, 'f', -1, 64))
|
bytes := []byte(strconv.FormatFloat(score, 'f', -1, 64))
|
||||||
db.addAof(utils.ToCmdLine3("zincrby", args...))
|
db.addAof(utils.ToCmdLine3("zincrby", args...))
|
||||||
return reply.MakeBulkReply(bytes)
|
return protocol.MakeBulkReply(bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
func undoZIncr(db *DB, args [][]byte) []CmdLine {
|
func undoZIncr(db *DB, args [][]byte) []CmdLine {
|
||||||
|
@@ -2,7 +2,7 @@ package database
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/hdt3213/godis/lib/utils"
|
"github.com/hdt3213/godis/lib/utils"
|
||||||
"github.com/hdt3213/godis/redis/reply/asserts"
|
"github.com/hdt3213/godis/redis/protocol/asserts"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
"strconv"
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
|
@@ -5,21 +5,21 @@ import (
|
|||||||
"github.com/hdt3213/godis/interface/database"
|
"github.com/hdt3213/godis/interface/database"
|
||||||
"github.com/hdt3213/godis/interface/redis"
|
"github.com/hdt3213/godis/interface/redis"
|
||||||
"github.com/hdt3213/godis/lib/utils"
|
"github.com/hdt3213/godis/lib/utils"
|
||||||
"github.com/hdt3213/godis/redis/reply"
|
"github.com/hdt3213/godis/redis/protocol"
|
||||||
"github.com/shopspring/decimal"
|
"github.com/shopspring/decimal"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (db *DB) getAsString(key string) ([]byte, reply.ErrorReply) {
|
func (db *DB) getAsString(key string) ([]byte, protocol.ErrorReply) {
|
||||||
entity, ok := db.GetEntity(key)
|
entity, ok := db.GetEntity(key)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
bytes, ok := entity.Data.([]byte)
|
bytes, ok := entity.Data.([]byte)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, &reply.WrongTypeErrReply{}
|
return nil, &protocol.WrongTypeErrReply{}
|
||||||
}
|
}
|
||||||
return bytes, nil
|
return bytes, nil
|
||||||
}
|
}
|
||||||
@@ -32,9 +32,9 @@ func execGet(db *DB, args [][]byte) redis.Reply {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if bytes == nil {
|
if bytes == nil {
|
||||||
return &reply.NullBulkReply{}
|
return &protocol.NullBulkReply{}
|
||||||
}
|
}
|
||||||
return reply.MakeBulkReply(bytes)
|
return protocol.MakeBulkReply(bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -58,49 +58,49 @@ func execSet(db *DB, args [][]byte) redis.Reply {
|
|||||||
arg := strings.ToUpper(string(args[i]))
|
arg := strings.ToUpper(string(args[i]))
|
||||||
if arg == "NX" { // insert
|
if arg == "NX" { // insert
|
||||||
if policy == updatePolicy {
|
if policy == updatePolicy {
|
||||||
return &reply.SyntaxErrReply{}
|
return &protocol.SyntaxErrReply{}
|
||||||
}
|
}
|
||||||
policy = insertPolicy
|
policy = insertPolicy
|
||||||
} else if arg == "XX" { // update policy
|
} else if arg == "XX" { // update policy
|
||||||
if policy == insertPolicy {
|
if policy == insertPolicy {
|
||||||
return &reply.SyntaxErrReply{}
|
return &protocol.SyntaxErrReply{}
|
||||||
}
|
}
|
||||||
policy = updatePolicy
|
policy = updatePolicy
|
||||||
} else if arg == "EX" { // ttl in seconds
|
} else if arg == "EX" { // ttl in seconds
|
||||||
if ttl != unlimitedTTL {
|
if ttl != unlimitedTTL {
|
||||||
// ttl has been set
|
// ttl has been set
|
||||||
return &reply.SyntaxErrReply{}
|
return &protocol.SyntaxErrReply{}
|
||||||
}
|
}
|
||||||
if i+1 >= len(args) {
|
if i+1 >= len(args) {
|
||||||
return &reply.SyntaxErrReply{}
|
return &protocol.SyntaxErrReply{}
|
||||||
}
|
}
|
||||||
ttlArg, err := strconv.ParseInt(string(args[i+1]), 10, 64)
|
ttlArg, err := strconv.ParseInt(string(args[i+1]), 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &reply.SyntaxErrReply{}
|
return &protocol.SyntaxErrReply{}
|
||||||
}
|
}
|
||||||
if ttlArg <= 0 {
|
if ttlArg <= 0 {
|
||||||
return reply.MakeErrReply("ERR invalid expire time in set")
|
return protocol.MakeErrReply("ERR invalid expire time in set")
|
||||||
}
|
}
|
||||||
ttl = ttlArg * 1000
|
ttl = ttlArg * 1000
|
||||||
i++ // skip next arg
|
i++ // skip next arg
|
||||||
} else if arg == "PX" { // ttl in milliseconds
|
} else if arg == "PX" { // ttl in milliseconds
|
||||||
if ttl != unlimitedTTL {
|
if ttl != unlimitedTTL {
|
||||||
return &reply.SyntaxErrReply{}
|
return &protocol.SyntaxErrReply{}
|
||||||
}
|
}
|
||||||
if i+1 >= len(args) {
|
if i+1 >= len(args) {
|
||||||
return &reply.SyntaxErrReply{}
|
return &protocol.SyntaxErrReply{}
|
||||||
}
|
}
|
||||||
ttlArg, err := strconv.ParseInt(string(args[i+1]), 10, 64)
|
ttlArg, err := strconv.ParseInt(string(args[i+1]), 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &reply.SyntaxErrReply{}
|
return &protocol.SyntaxErrReply{}
|
||||||
}
|
}
|
||||||
if ttlArg <= 0 {
|
if ttlArg <= 0 {
|
||||||
return reply.MakeErrReply("ERR invalid expire time in set")
|
return protocol.MakeErrReply("ERR invalid expire time in set")
|
||||||
}
|
}
|
||||||
ttl = ttlArg
|
ttl = ttlArg
|
||||||
i++ // skip next arg
|
i++ // skip next arg
|
||||||
} else {
|
} else {
|
||||||
return &reply.SyntaxErrReply{}
|
return &protocol.SyntaxErrReply{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -136,9 +136,9 @@ func execSet(db *DB, args [][]byte) redis.Reply {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if result > 0 {
|
if result > 0 {
|
||||||
return &reply.OkReply{}
|
return &protocol.OkReply{}
|
||||||
}
|
}
|
||||||
return &reply.NullBulkReply{}
|
return &protocol.NullBulkReply{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// execSetNX sets string if not exists
|
// execSetNX sets string if not exists
|
||||||
@@ -150,7 +150,7 @@ func execSetNX(db *DB, args [][]byte) redis.Reply {
|
|||||||
}
|
}
|
||||||
result := db.PutIfAbsent(key, entity)
|
result := db.PutIfAbsent(key, entity)
|
||||||
db.addAof(utils.ToCmdLine3("setnx", args...))
|
db.addAof(utils.ToCmdLine3("setnx", args...))
|
||||||
return reply.MakeIntReply(int64(result))
|
return protocol.MakeIntReply(int64(result))
|
||||||
}
|
}
|
||||||
|
|
||||||
// execSetEX sets string and its ttl
|
// execSetEX sets string and its ttl
|
||||||
@@ -160,10 +160,10 @@ func execSetEX(db *DB, args [][]byte) redis.Reply {
|
|||||||
|
|
||||||
ttlArg, err := strconv.ParseInt(string(args[1]), 10, 64)
|
ttlArg, err := strconv.ParseInt(string(args[1]), 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &reply.SyntaxErrReply{}
|
return &protocol.SyntaxErrReply{}
|
||||||
}
|
}
|
||||||
if ttlArg <= 0 {
|
if ttlArg <= 0 {
|
||||||
return reply.MakeErrReply("ERR invalid expire time in setex")
|
return protocol.MakeErrReply("ERR invalid expire time in setex")
|
||||||
}
|
}
|
||||||
ttl := ttlArg * 1000
|
ttl := ttlArg * 1000
|
||||||
|
|
||||||
@@ -176,7 +176,7 @@ func execSetEX(db *DB, args [][]byte) redis.Reply {
|
|||||||
db.Expire(key, expireTime)
|
db.Expire(key, expireTime)
|
||||||
db.addAof(utils.ToCmdLine3("setex", args...))
|
db.addAof(utils.ToCmdLine3("setex", args...))
|
||||||
db.addAof(aof.MakeExpireCmd(key, expireTime).Args)
|
db.addAof(aof.MakeExpireCmd(key, expireTime).Args)
|
||||||
return &reply.OkReply{}
|
return &protocol.OkReply{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// execPSetEX set a key's time to live in milliseconds
|
// execPSetEX set a key's time to live in milliseconds
|
||||||
@@ -186,10 +186,10 @@ func execPSetEX(db *DB, args [][]byte) redis.Reply {
|
|||||||
|
|
||||||
ttlArg, err := strconv.ParseInt(string(args[1]), 10, 64)
|
ttlArg, err := strconv.ParseInt(string(args[1]), 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return &reply.SyntaxErrReply{}
|
return &protocol.SyntaxErrReply{}
|
||||||
}
|
}
|
||||||
if ttlArg <= 0 {
|
if ttlArg <= 0 {
|
||||||
return reply.MakeErrReply("ERR invalid expire time in setex")
|
return protocol.MakeErrReply("ERR invalid expire time in setex")
|
||||||
}
|
}
|
||||||
|
|
||||||
entity := &database.DataEntity{
|
entity := &database.DataEntity{
|
||||||
@@ -202,7 +202,7 @@ func execPSetEX(db *DB, args [][]byte) redis.Reply {
|
|||||||
db.addAof(utils.ToCmdLine3("setex", args...))
|
db.addAof(utils.ToCmdLine3("setex", args...))
|
||||||
db.addAof(aof.MakeExpireCmd(key, expireTime).Args)
|
db.addAof(aof.MakeExpireCmd(key, expireTime).Args)
|
||||||
|
|
||||||
return &reply.OkReply{}
|
return &protocol.OkReply{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func prepareMSet(args [][]byte) ([]string, []string) {
|
func prepareMSet(args [][]byte) ([]string, []string) {
|
||||||
@@ -222,7 +222,7 @@ func undoMSet(db *DB, args [][]byte) []CmdLine {
|
|||||||
// execMSet sets multi key-value in database
|
// execMSet sets multi key-value in database
|
||||||
func execMSet(db *DB, args [][]byte) redis.Reply {
|
func execMSet(db *DB, args [][]byte) redis.Reply {
|
||||||
if len(args)%2 != 0 {
|
if len(args)%2 != 0 {
|
||||||
return reply.MakeSyntaxErrReply()
|
return protocol.MakeSyntaxErrReply()
|
||||||
}
|
}
|
||||||
|
|
||||||
size := len(args) / 2
|
size := len(args) / 2
|
||||||
@@ -238,7 +238,7 @@ func execMSet(db *DB, args [][]byte) redis.Reply {
|
|||||||
db.PutEntity(key, &database.DataEntity{Data: value})
|
db.PutEntity(key, &database.DataEntity{Data: value})
|
||||||
}
|
}
|
||||||
db.addAof(utils.ToCmdLine3("mset", args...))
|
db.addAof(utils.ToCmdLine3("mset", args...))
|
||||||
return &reply.OkReply{}
|
return &protocol.OkReply{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func prepareMGet(args [][]byte) ([]string, []string) {
|
func prepareMGet(args [][]byte) ([]string, []string) {
|
||||||
@@ -260,7 +260,7 @@ func execMGet(db *DB, args [][]byte) redis.Reply {
|
|||||||
for i, key := range keys {
|
for i, key := range keys {
|
||||||
bytes, err := db.getAsString(key)
|
bytes, err := db.getAsString(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
_, isWrongType := err.(*reply.WrongTypeErrReply)
|
_, isWrongType := err.(*protocol.WrongTypeErrReply)
|
||||||
if isWrongType {
|
if isWrongType {
|
||||||
result[i] = nil
|
result[i] = nil
|
||||||
continue
|
continue
|
||||||
@@ -271,14 +271,14 @@ func execMGet(db *DB, args [][]byte) redis.Reply {
|
|||||||
result[i] = bytes // nil or []byte
|
result[i] = bytes // nil or []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
return reply.MakeMultiBulkReply(result)
|
return protocol.MakeMultiBulkReply(result)
|
||||||
}
|
}
|
||||||
|
|
||||||
// execMSetNX sets multi key-value in database, only if none of the given keys exist
|
// execMSetNX sets multi key-value in database, only if none of the given keys exist
|
||||||
func execMSetNX(db *DB, args [][]byte) redis.Reply {
|
func execMSetNX(db *DB, args [][]byte) redis.Reply {
|
||||||
// parse args
|
// parse args
|
||||||
if len(args)%2 != 0 {
|
if len(args)%2 != 0 {
|
||||||
return reply.MakeSyntaxErrReply()
|
return protocol.MakeSyntaxErrReply()
|
||||||
}
|
}
|
||||||
size := len(args) / 2
|
size := len(args) / 2
|
||||||
values := make([][]byte, size)
|
values := make([][]byte, size)
|
||||||
@@ -291,7 +291,7 @@ func execMSetNX(db *DB, args [][]byte) redis.Reply {
|
|||||||
for _, key := range keys {
|
for _, key := range keys {
|
||||||
_, exists := db.GetEntity(key)
|
_, exists := db.GetEntity(key)
|
||||||
if exists {
|
if exists {
|
||||||
return reply.MakeIntReply(0)
|
return protocol.MakeIntReply(0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -300,7 +300,7 @@ func execMSetNX(db *DB, args [][]byte) redis.Reply {
|
|||||||
db.PutEntity(key, &database.DataEntity{Data: value})
|
db.PutEntity(key, &database.DataEntity{Data: value})
|
||||||
}
|
}
|
||||||
db.addAof(utils.ToCmdLine3("msetnx", args...))
|
db.addAof(utils.ToCmdLine3("msetnx", args...))
|
||||||
return reply.MakeIntReply(1)
|
return protocol.MakeIntReply(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// execGetSet sets value of a string-type key and returns its old value
|
// execGetSet sets value of a string-type key and returns its old value
|
||||||
@@ -317,9 +317,9 @@ func execGetSet(db *DB, args [][]byte) redis.Reply {
|
|||||||
db.Persist(key) // override ttl
|
db.Persist(key) // override ttl
|
||||||
db.addAof(utils.ToCmdLine3("getset", args...))
|
db.addAof(utils.ToCmdLine3("getset", args...))
|
||||||
if old == nil {
|
if old == nil {
|
||||||
return new(reply.NullBulkReply)
|
return new(protocol.NullBulkReply)
|
||||||
}
|
}
|
||||||
return reply.MakeBulkReply(old)
|
return protocol.MakeBulkReply(old)
|
||||||
}
|
}
|
||||||
|
|
||||||
// execIncr increments the integer value of a key by one
|
// execIncr increments the integer value of a key by one
|
||||||
@@ -333,19 +333,19 @@ func execIncr(db *DB, args [][]byte) redis.Reply {
|
|||||||
if bytes != nil {
|
if bytes != nil {
|
||||||
val, err := strconv.ParseInt(string(bytes), 10, 64)
|
val, err := strconv.ParseInt(string(bytes), 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reply.MakeErrReply("ERR value is not an integer or out of range")
|
return protocol.MakeErrReply("ERR value is not an integer or out of range")
|
||||||
}
|
}
|
||||||
db.PutEntity(key, &database.DataEntity{
|
db.PutEntity(key, &database.DataEntity{
|
||||||
Data: []byte(strconv.FormatInt(val+1, 10)),
|
Data: []byte(strconv.FormatInt(val+1, 10)),
|
||||||
})
|
})
|
||||||
db.addAof(utils.ToCmdLine3("incr", args...))
|
db.addAof(utils.ToCmdLine3("incr", args...))
|
||||||
return reply.MakeIntReply(val + 1)
|
return protocol.MakeIntReply(val + 1)
|
||||||
}
|
}
|
||||||
db.PutEntity(key, &database.DataEntity{
|
db.PutEntity(key, &database.DataEntity{
|
||||||
Data: []byte("1"),
|
Data: []byte("1"),
|
||||||
})
|
})
|
||||||
db.addAof(utils.ToCmdLine3("incr", args...))
|
db.addAof(utils.ToCmdLine3("incr", args...))
|
||||||
return reply.MakeIntReply(1)
|
return protocol.MakeIntReply(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// execIncrBy increments the integer value of a key by given value
|
// execIncrBy increments the integer value of a key by given value
|
||||||
@@ -354,7 +354,7 @@ func execIncrBy(db *DB, args [][]byte) redis.Reply {
|
|||||||
rawDelta := string(args[1])
|
rawDelta := string(args[1])
|
||||||
delta, err := strconv.ParseInt(rawDelta, 10, 64)
|
delta, err := strconv.ParseInt(rawDelta, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reply.MakeErrReply("ERR value is not an integer or out of range")
|
return protocol.MakeErrReply("ERR value is not an integer or out of range")
|
||||||
}
|
}
|
||||||
|
|
||||||
bytes, errReply := db.getAsString(key)
|
bytes, errReply := db.getAsString(key)
|
||||||
@@ -365,19 +365,19 @@ func execIncrBy(db *DB, args [][]byte) redis.Reply {
|
|||||||
// existed value
|
// existed value
|
||||||
val, err := strconv.ParseInt(string(bytes), 10, 64)
|
val, err := strconv.ParseInt(string(bytes), 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reply.MakeErrReply("ERR value is not an integer or out of range")
|
return protocol.MakeErrReply("ERR value is not an integer or out of range")
|
||||||
}
|
}
|
||||||
db.PutEntity(key, &database.DataEntity{
|
db.PutEntity(key, &database.DataEntity{
|
||||||
Data: []byte(strconv.FormatInt(val+delta, 10)),
|
Data: []byte(strconv.FormatInt(val+delta, 10)),
|
||||||
})
|
})
|
||||||
db.addAof(utils.ToCmdLine3("incrby", args...))
|
db.addAof(utils.ToCmdLine3("incrby", args...))
|
||||||
return reply.MakeIntReply(val + delta)
|
return protocol.MakeIntReply(val + delta)
|
||||||
}
|
}
|
||||||
db.PutEntity(key, &database.DataEntity{
|
db.PutEntity(key, &database.DataEntity{
|
||||||
Data: args[1],
|
Data: args[1],
|
||||||
})
|
})
|
||||||
db.addAof(utils.ToCmdLine3("incrby", args...))
|
db.addAof(utils.ToCmdLine3("incrby", args...))
|
||||||
return reply.MakeIntReply(delta)
|
return protocol.MakeIntReply(delta)
|
||||||
}
|
}
|
||||||
|
|
||||||
// execIncrByFloat increments the float value of a key by given value
|
// execIncrByFloat increments the float value of a key by given value
|
||||||
@@ -386,7 +386,7 @@ func execIncrByFloat(db *DB, args [][]byte) redis.Reply {
|
|||||||
rawDelta := string(args[1])
|
rawDelta := string(args[1])
|
||||||
delta, err := decimal.NewFromString(rawDelta)
|
delta, err := decimal.NewFromString(rawDelta)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reply.MakeErrReply("ERR value is not a valid float")
|
return protocol.MakeErrReply("ERR value is not a valid float")
|
||||||
}
|
}
|
||||||
|
|
||||||
bytes, errReply := db.getAsString(key)
|
bytes, errReply := db.getAsString(key)
|
||||||
@@ -396,20 +396,20 @@ func execIncrByFloat(db *DB, args [][]byte) redis.Reply {
|
|||||||
if bytes != nil {
|
if bytes != nil {
|
||||||
val, err := decimal.NewFromString(string(bytes))
|
val, err := decimal.NewFromString(string(bytes))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reply.MakeErrReply("ERR value is not a valid float")
|
return protocol.MakeErrReply("ERR value is not a valid float")
|
||||||
}
|
}
|
||||||
resultBytes := []byte(val.Add(delta).String())
|
resultBytes := []byte(val.Add(delta).String())
|
||||||
db.PutEntity(key, &database.DataEntity{
|
db.PutEntity(key, &database.DataEntity{
|
||||||
Data: resultBytes,
|
Data: resultBytes,
|
||||||
})
|
})
|
||||||
db.addAof(utils.ToCmdLine3("incrbyfloat", args...))
|
db.addAof(utils.ToCmdLine3("incrbyfloat", args...))
|
||||||
return reply.MakeBulkReply(resultBytes)
|
return protocol.MakeBulkReply(resultBytes)
|
||||||
}
|
}
|
||||||
db.PutEntity(key, &database.DataEntity{
|
db.PutEntity(key, &database.DataEntity{
|
||||||
Data: args[1],
|
Data: args[1],
|
||||||
})
|
})
|
||||||
db.addAof(utils.ToCmdLine3("incrbyfloat", args...))
|
db.addAof(utils.ToCmdLine3("incrbyfloat", args...))
|
||||||
return reply.MakeBulkReply(args[1])
|
return protocol.MakeBulkReply(args[1])
|
||||||
}
|
}
|
||||||
|
|
||||||
// execDecr decrements the integer value of a key by one
|
// execDecr decrements the integer value of a key by one
|
||||||
@@ -423,20 +423,20 @@ func execDecr(db *DB, args [][]byte) redis.Reply {
|
|||||||
if bytes != nil {
|
if bytes != nil {
|
||||||
val, err := strconv.ParseInt(string(bytes), 10, 64)
|
val, err := strconv.ParseInt(string(bytes), 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reply.MakeErrReply("ERR value is not an integer or out of range")
|
return protocol.MakeErrReply("ERR value is not an integer or out of range")
|
||||||
}
|
}
|
||||||
db.PutEntity(key, &database.DataEntity{
|
db.PutEntity(key, &database.DataEntity{
|
||||||
Data: []byte(strconv.FormatInt(val-1, 10)),
|
Data: []byte(strconv.FormatInt(val-1, 10)),
|
||||||
})
|
})
|
||||||
db.addAof(utils.ToCmdLine3("decr", args...))
|
db.addAof(utils.ToCmdLine3("decr", args...))
|
||||||
return reply.MakeIntReply(val - 1)
|
return protocol.MakeIntReply(val - 1)
|
||||||
}
|
}
|
||||||
entity := &database.DataEntity{
|
entity := &database.DataEntity{
|
||||||
Data: []byte("-1"),
|
Data: []byte("-1"),
|
||||||
}
|
}
|
||||||
db.PutEntity(key, entity)
|
db.PutEntity(key, entity)
|
||||||
db.addAof(utils.ToCmdLine3("decr", args...))
|
db.addAof(utils.ToCmdLine3("decr", args...))
|
||||||
return reply.MakeIntReply(-1)
|
return protocol.MakeIntReply(-1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// execDecrBy decrements the integer value of a key by onedecrement
|
// execDecrBy decrements the integer value of a key by onedecrement
|
||||||
@@ -445,7 +445,7 @@ func execDecrBy(db *DB, args [][]byte) redis.Reply {
|
|||||||
rawDelta := string(args[1])
|
rawDelta := string(args[1])
|
||||||
delta, err := strconv.ParseInt(rawDelta, 10, 64)
|
delta, err := strconv.ParseInt(rawDelta, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reply.MakeErrReply("ERR value is not an integer or out of range")
|
return protocol.MakeErrReply("ERR value is not an integer or out of range")
|
||||||
}
|
}
|
||||||
|
|
||||||
bytes, errReply := db.getAsString(key)
|
bytes, errReply := db.getAsString(key)
|
||||||
@@ -455,20 +455,20 @@ func execDecrBy(db *DB, args [][]byte) redis.Reply {
|
|||||||
if bytes != nil {
|
if bytes != nil {
|
||||||
val, err := strconv.ParseInt(string(bytes), 10, 64)
|
val, err := strconv.ParseInt(string(bytes), 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return reply.MakeErrReply("ERR value is not an integer or out of range")
|
return protocol.MakeErrReply("ERR value is not an integer or out of range")
|
||||||
}
|
}
|
||||||
db.PutEntity(key, &database.DataEntity{
|
db.PutEntity(key, &database.DataEntity{
|
||||||
Data: []byte(strconv.FormatInt(val-delta, 10)),
|
Data: []byte(strconv.FormatInt(val-delta, 10)),
|
||||||
})
|
})
|
||||||
db.addAof(utils.ToCmdLine3("decrby", args...))
|
db.addAof(utils.ToCmdLine3("decrby", args...))
|
||||||
return reply.MakeIntReply(val - delta)
|
return protocol.MakeIntReply(val - delta)
|
||||||
}
|
}
|
||||||
valueStr := strconv.FormatInt(-delta, 10)
|
valueStr := strconv.FormatInt(-delta, 10)
|
||||||
db.PutEntity(key, &database.DataEntity{
|
db.PutEntity(key, &database.DataEntity{
|
||||||
Data: []byte(valueStr),
|
Data: []byte(valueStr),
|
||||||
})
|
})
|
||||||
db.addAof(utils.ToCmdLine3("decrby", args...))
|
db.addAof(utils.ToCmdLine3("decrby", args...))
|
||||||
return reply.MakeIntReply(-delta)
|
return protocol.MakeIntReply(-delta)
|
||||||
}
|
}
|
||||||
|
|
||||||
// execStrLen returns len of string value bound to the given key
|
// execStrLen returns len of string value bound to the given key
|
||||||
@@ -479,9 +479,9 @@ func execStrLen(db *DB, args [][]byte) redis.Reply {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if bytes == nil {
|
if bytes == nil {
|
||||||
return reply.MakeIntReply(0)
|
return protocol.MakeIntReply(0)
|
||||||
}
|
}
|
||||||
return reply.MakeIntReply(int64(len(bytes)))
|
return protocol.MakeIntReply(int64(len(bytes)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// execAppend sets string value to the given key
|
// execAppend sets string value to the given key
|
||||||
@@ -496,7 +496,7 @@ func execAppend(db *DB, args [][]byte) redis.Reply {
|
|||||||
Data: bytes,
|
Data: bytes,
|
||||||
})
|
})
|
||||||
db.addAof(utils.ToCmdLine3("append", args...))
|
db.addAof(utils.ToCmdLine3("append", args...))
|
||||||
return reply.MakeIntReply(int64(len(bytes)))
|
return protocol.MakeIntReply(int64(len(bytes)))
|
||||||
}
|
}
|
||||||
|
|
||||||
// execSetRange overwrites part of the string stored at key, starting at the specified offset.
|
// execSetRange overwrites part of the string stored at key, starting at the specified offset.
|
||||||
@@ -505,7 +505,7 @@ func execSetRange(db *DB, args [][]byte) redis.Reply {
|
|||||||
key := string(args[0])
|
key := string(args[0])
|
||||||
offset, errNative := strconv.ParseInt(string(args[1]), 10, 64)
|
offset, errNative := strconv.ParseInt(string(args[1]), 10, 64)
|
||||||
if errNative != nil {
|
if errNative != nil {
|
||||||
return reply.MakeErrReply(errNative.Error())
|
return protocol.MakeErrReply(errNative.Error())
|
||||||
}
|
}
|
||||||
value := args[2]
|
value := args[2]
|
||||||
bytes, err := db.getAsString(key)
|
bytes, err := db.getAsString(key)
|
||||||
@@ -531,18 +531,18 @@ func execSetRange(db *DB, args [][]byte) redis.Reply {
|
|||||||
Data: bytes,
|
Data: bytes,
|
||||||
})
|
})
|
||||||
db.addAof(utils.ToCmdLine3("setRange", args...))
|
db.addAof(utils.ToCmdLine3("setRange", args...))
|
||||||
return reply.MakeIntReply(int64(len(bytes)))
|
return protocol.MakeIntReply(int64(len(bytes)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func execGetRange(db *DB, args [][]byte) redis.Reply {
|
func execGetRange(db *DB, args [][]byte) redis.Reply {
|
||||||
key := string(args[0])
|
key := string(args[0])
|
||||||
startIdx, errNative := strconv.ParseInt(string(args[1]), 10, 64)
|
startIdx, errNative := strconv.ParseInt(string(args[1]), 10, 64)
|
||||||
if errNative != nil {
|
if errNative != nil {
|
||||||
return reply.MakeErrReply(errNative.Error())
|
return protocol.MakeErrReply(errNative.Error())
|
||||||
}
|
}
|
||||||
endIdx, errNative := strconv.ParseInt(string(args[2]), 10, 64)
|
endIdx, errNative := strconv.ParseInt(string(args[2]), 10, 64)
|
||||||
if errNative != nil {
|
if errNative != nil {
|
||||||
return reply.MakeErrReply(errNative.Error())
|
return protocol.MakeErrReply(errNative.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
bytes, err := db.getAsString(key)
|
bytes, err := db.getAsString(key)
|
||||||
@@ -551,19 +551,19 @@ func execGetRange(db *DB, args [][]byte) redis.Reply {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if bytes == nil {
|
if bytes == nil {
|
||||||
return reply.MakeNullBulkReply()
|
return protocol.MakeNullBulkReply()
|
||||||
}
|
}
|
||||||
|
|
||||||
bytesLen := int64(len(bytes))
|
bytesLen := int64(len(bytes))
|
||||||
if startIdx < -1*bytesLen {
|
if startIdx < -1*bytesLen {
|
||||||
return &reply.NullBulkReply{}
|
return &protocol.NullBulkReply{}
|
||||||
} else if startIdx < 0 {
|
} else if startIdx < 0 {
|
||||||
startIdx = bytesLen + startIdx
|
startIdx = bytesLen + startIdx
|
||||||
} else if startIdx >= bytesLen {
|
} else if startIdx >= bytesLen {
|
||||||
return &reply.NullBulkReply{}
|
return &protocol.NullBulkReply{}
|
||||||
}
|
}
|
||||||
if endIdx < -1*bytesLen {
|
if endIdx < -1*bytesLen {
|
||||||
return &reply.NullBulkReply{}
|
return &protocol.NullBulkReply{}
|
||||||
} else if endIdx < 0 {
|
} else if endIdx < 0 {
|
||||||
endIdx = bytesLen + endIdx + 1
|
endIdx = bytesLen + endIdx + 1
|
||||||
} else if endIdx < bytesLen {
|
} else if endIdx < bytesLen {
|
||||||
@@ -572,10 +572,10 @@ func execGetRange(db *DB, args [][]byte) redis.Reply {
|
|||||||
endIdx = bytesLen
|
endIdx = bytesLen
|
||||||
}
|
}
|
||||||
if startIdx > endIdx {
|
if startIdx > endIdx {
|
||||||
return reply.MakeNullBulkReply()
|
return protocol.MakeNullBulkReply()
|
||||||
}
|
}
|
||||||
|
|
||||||
return reply.MakeBulkReply(bytes[startIdx:endIdx])
|
return protocol.MakeBulkReply(bytes[startIdx:endIdx])
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@@ -3,8 +3,8 @@ package database
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/hdt3213/godis/lib/utils"
|
"github.com/hdt3213/godis/lib/utils"
|
||||||
"github.com/hdt3213/godis/redis/reply"
|
"github.com/hdt3213/godis/redis/protocol"
|
||||||
"github.com/hdt3213/godis/redis/reply/asserts"
|
"github.com/hdt3213/godis/redis/protocol/asserts"
|
||||||
"strconv"
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
@@ -18,7 +18,7 @@ func TestSet2(t *testing.T) {
|
|||||||
for i := 0; i < 1000; i++ {
|
for i := 0; i < 1000; i++ {
|
||||||
testDB.Exec(nil, utils.ToCmdLine("SET", key, value))
|
testDB.Exec(nil, utils.ToCmdLine("SET", key, value))
|
||||||
actual := testDB.Exec(nil, utils.ToCmdLine("GET", key))
|
actual := testDB.Exec(nil, utils.ToCmdLine("GET", key))
|
||||||
expected := reply.MakeBulkReply([]byte(value))
|
expected := protocol.MakeBulkReply([]byte(value))
|
||||||
if !utils.BytesEquals(actual.ToBytes(), expected.ToBytes()) {
|
if !utils.BytesEquals(actual.ToBytes(), expected.ToBytes()) {
|
||||||
t.Error("expected: " + string(expected.ToBytes()) + ", actual: " + string(actual.ToBytes()))
|
t.Error("expected: " + string(expected.ToBytes()) + ", actual: " + string(actual.ToBytes()))
|
||||||
}
|
}
|
||||||
@@ -33,14 +33,14 @@ func TestSet(t *testing.T) {
|
|||||||
// normal set
|
// normal set
|
||||||
testDB.Exec(nil, utils.ToCmdLine("SET", key, value))
|
testDB.Exec(nil, utils.ToCmdLine("SET", key, value))
|
||||||
actual := testDB.Exec(nil, utils.ToCmdLine("GET", key))
|
actual := testDB.Exec(nil, utils.ToCmdLine("GET", key))
|
||||||
expected := reply.MakeBulkReply([]byte(value))
|
expected := protocol.MakeBulkReply([]byte(value))
|
||||||
if !utils.BytesEquals(actual.ToBytes(), expected.ToBytes()) {
|
if !utils.BytesEquals(actual.ToBytes(), expected.ToBytes()) {
|
||||||
t.Error("expected: " + string(expected.ToBytes()) + ", actual: " + string(actual.ToBytes()))
|
t.Error("expected: " + string(expected.ToBytes()) + ", actual: " + string(actual.ToBytes()))
|
||||||
}
|
}
|
||||||
|
|
||||||
// set nx
|
// set nx
|
||||||
actual = testDB.Exec(nil, utils.ToCmdLine("SET", key, value, "NX"))
|
actual = testDB.Exec(nil, utils.ToCmdLine("SET", key, value, "NX"))
|
||||||
if _, ok := actual.(*reply.NullBulkReply); !ok {
|
if _, ok := actual.(*protocol.NullBulkReply); !ok {
|
||||||
t.Error("expected true actual false")
|
t.Error("expected true actual false")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -49,7 +49,7 @@ func TestSet(t *testing.T) {
|
|||||||
value = utils.RandString(10)
|
value = utils.RandString(10)
|
||||||
actual = testDB.Exec(nil, utils.ToCmdLine("SET", key, value, "NX"))
|
actual = testDB.Exec(nil, utils.ToCmdLine("SET", key, value, "NX"))
|
||||||
actual = testDB.Exec(nil, utils.ToCmdLine("GET", key))
|
actual = testDB.Exec(nil, utils.ToCmdLine("GET", key))
|
||||||
expected = reply.MakeBulkReply([]byte(value))
|
expected = protocol.MakeBulkReply([]byte(value))
|
||||||
if !utils.BytesEquals(actual.ToBytes(), expected.ToBytes()) {
|
if !utils.BytesEquals(actual.ToBytes(), expected.ToBytes()) {
|
||||||
t.Error("expected: " + string(expected.ToBytes()) + ", actual: " + string(actual.ToBytes()))
|
t.Error("expected: " + string(expected.ToBytes()) + ", actual: " + string(actual.ToBytes()))
|
||||||
}
|
}
|
||||||
@@ -59,7 +59,7 @@ func TestSet(t *testing.T) {
|
|||||||
key = utils.RandString(10)
|
key = utils.RandString(10)
|
||||||
value = utils.RandString(10)
|
value = utils.RandString(10)
|
||||||
actual = testDB.Exec(nil, utils.ToCmdLine("SET", key, value, "XX"))
|
actual = testDB.Exec(nil, utils.ToCmdLine("SET", key, value, "XX"))
|
||||||
if _, ok := actual.(*reply.NullBulkReply); !ok {
|
if _, ok := actual.(*protocol.NullBulkReply); !ok {
|
||||||
t.Error("expected true actually false ")
|
t.Error("expected true actually false ")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -77,9 +77,9 @@ func TestSet(t *testing.T) {
|
|||||||
asserts.AssertBulkReply(t, actual, value)
|
asserts.AssertBulkReply(t, actual, value)
|
||||||
actual = execTTL(testDB, utils.ToCmdLine(key))
|
actual = execTTL(testDB, utils.ToCmdLine(key))
|
||||||
actual = testDB.Exec(nil, utils.ToCmdLine("TTL", key))
|
actual = testDB.Exec(nil, utils.ToCmdLine("TTL", key))
|
||||||
intResult, ok := actual.(*reply.IntReply)
|
intResult, ok := actual.(*protocol.IntReply)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Error(fmt.Sprintf("expected int reply, actually %s", actual.ToBytes()))
|
t.Error(fmt.Sprintf("expected int protocol, actually %s", actual.ToBytes()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if intResult.Code <= 0 || intResult.Code > 1000 {
|
if intResult.Code <= 0 || intResult.Code > 1000 {
|
||||||
@@ -94,9 +94,9 @@ func TestSet(t *testing.T) {
|
|||||||
actual = testDB.Exec(nil, utils.ToCmdLine("GET", key))
|
actual = testDB.Exec(nil, utils.ToCmdLine("GET", key))
|
||||||
asserts.AssertBulkReply(t, actual, value)
|
asserts.AssertBulkReply(t, actual, value)
|
||||||
actual = testDB.Exec(nil, utils.ToCmdLine("TTL", key))
|
actual = testDB.Exec(nil, utils.ToCmdLine("TTL", key))
|
||||||
intResult, ok = actual.(*reply.IntReply)
|
intResult, ok = actual.(*protocol.IntReply)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Error(fmt.Sprintf("expected int reply, actually %s", actual.ToBytes()))
|
t.Error(fmt.Sprintf("expected int protocol, actually %s", actual.ToBytes()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if intResult.Code <= 0 || intResult.Code > 1000 {
|
if intResult.Code <= 0 || intResult.Code > 1000 {
|
||||||
@@ -111,13 +111,13 @@ func TestSetNX(t *testing.T) {
|
|||||||
value := utils.RandString(10)
|
value := utils.RandString(10)
|
||||||
testDB.Exec(nil, utils.ToCmdLine("SETNX", key, value))
|
testDB.Exec(nil, utils.ToCmdLine("SETNX", key, value))
|
||||||
actual := testDB.Exec(nil, utils.ToCmdLine("GET", key))
|
actual := testDB.Exec(nil, utils.ToCmdLine("GET", key))
|
||||||
expected := reply.MakeBulkReply([]byte(value))
|
expected := protocol.MakeBulkReply([]byte(value))
|
||||||
if !utils.BytesEquals(actual.ToBytes(), expected.ToBytes()) {
|
if !utils.BytesEquals(actual.ToBytes(), expected.ToBytes()) {
|
||||||
t.Error("expected: " + string(expected.ToBytes()) + ", actual: " + string(actual.ToBytes()))
|
t.Error("expected: " + string(expected.ToBytes()) + ", actual: " + string(actual.ToBytes()))
|
||||||
}
|
}
|
||||||
|
|
||||||
actual = testDB.Exec(nil, utils.ToCmdLine("SETNX", key, value))
|
actual = testDB.Exec(nil, utils.ToCmdLine("SETNX", key, value))
|
||||||
expected2 := reply.MakeIntReply(int64(0))
|
expected2 := protocol.MakeIntReply(int64(0))
|
||||||
if !utils.BytesEquals(actual.ToBytes(), expected2.ToBytes()) {
|
if !utils.BytesEquals(actual.ToBytes(), expected2.ToBytes()) {
|
||||||
t.Error("expected: " + string(expected2.ToBytes()) + ", actual: " + string(actual.ToBytes()))
|
t.Error("expected: " + string(expected2.ToBytes()) + ", actual: " + string(actual.ToBytes()))
|
||||||
}
|
}
|
||||||
@@ -133,9 +133,9 @@ func TestSetEX(t *testing.T) {
|
|||||||
actual := testDB.Exec(nil, utils.ToCmdLine("GET", key))
|
actual := testDB.Exec(nil, utils.ToCmdLine("GET", key))
|
||||||
asserts.AssertBulkReply(t, actual, value)
|
asserts.AssertBulkReply(t, actual, value)
|
||||||
actual = testDB.Exec(nil, utils.ToCmdLine("TTL", key))
|
actual = testDB.Exec(nil, utils.ToCmdLine("TTL", key))
|
||||||
intResult, ok := actual.(*reply.IntReply)
|
intResult, ok := actual.(*protocol.IntReply)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Error(fmt.Sprintf("expected int reply, actually %s", actual.ToBytes()))
|
t.Error(fmt.Sprintf("expected int protocol, actually %s", actual.ToBytes()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if intResult.Code <= 0 || intResult.Code > 1000 {
|
if intResult.Code <= 0 || intResult.Code > 1000 {
|
||||||
@@ -154,9 +154,9 @@ func TestPSetEX(t *testing.T) {
|
|||||||
actual := testDB.Exec(nil, utils.ToCmdLine("GET", key))
|
actual := testDB.Exec(nil, utils.ToCmdLine("GET", key))
|
||||||
asserts.AssertBulkReply(t, actual, value)
|
asserts.AssertBulkReply(t, actual, value)
|
||||||
actual = testDB.Exec(nil, utils.ToCmdLine("PTTL", key))
|
actual = testDB.Exec(nil, utils.ToCmdLine("PTTL", key))
|
||||||
intResult, ok := actual.(*reply.IntReply)
|
intResult, ok := actual.(*protocol.IntReply)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Error(fmt.Sprintf("expected int reply, actually %s", actual.ToBytes()))
|
t.Error(fmt.Sprintf("expected int protocol, actually %s", actual.ToBytes()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if intResult.Code <= 0 || intResult.Code > 1000000 {
|
if intResult.Code <= 0 || intResult.Code > 1000000 {
|
||||||
@@ -179,7 +179,7 @@ func TestMSet(t *testing.T) {
|
|||||||
}
|
}
|
||||||
testDB.Exec(nil, utils.ToCmdLine2("MSET", args...))
|
testDB.Exec(nil, utils.ToCmdLine2("MSET", args...))
|
||||||
actual := testDB.Exec(nil, utils.ToCmdLine2("MGET", keys...))
|
actual := testDB.Exec(nil, utils.ToCmdLine2("MGET", keys...))
|
||||||
expected := reply.MakeMultiBulkReply(values)
|
expected := protocol.MakeMultiBulkReply(values)
|
||||||
if !utils.BytesEquals(actual.ToBytes(), expected.ToBytes()) {
|
if !utils.BytesEquals(actual.ToBytes(), expected.ToBytes()) {
|
||||||
t.Error("expected: " + string(expected.ToBytes()) + ", actual: " + string(actual.ToBytes()))
|
t.Error("expected: " + string(expected.ToBytes()) + ", actual: " + string(actual.ToBytes()))
|
||||||
}
|
}
|
||||||
@@ -190,7 +190,7 @@ func TestMSet(t *testing.T) {
|
|||||||
key2 := utils.RandString(10)
|
key2 := utils.RandString(10)
|
||||||
testDB.Exec(nil, utils.ToCmdLine2("LPush", key2, key2))
|
testDB.Exec(nil, utils.ToCmdLine2("LPush", key2, key2))
|
||||||
actual = testDB.Exec(nil, utils.ToCmdLine2("MGET", key1, key2))
|
actual = testDB.Exec(nil, utils.ToCmdLine2("MGET", key1, key2))
|
||||||
arr := actual.(*reply.MultiBulkReply)
|
arr := actual.(*protocol.MultiBulkReply)
|
||||||
if string(arr.Args[0]) != key1 {
|
if string(arr.Args[0]) != key1 {
|
||||||
t.Error("expected: " + key1 + ", actual: " + string(arr.Args[1]))
|
t.Error("expected: " + key1 + ", actual: " + string(arr.Args[1]))
|
||||||
}
|
}
|
||||||
@@ -206,7 +206,7 @@ func TestIncr(t *testing.T) {
|
|||||||
for i := 0; i < size; i++ {
|
for i := 0; i < size; i++ {
|
||||||
testDB.Exec(nil, utils.ToCmdLine("INCR", key))
|
testDB.Exec(nil, utils.ToCmdLine("INCR", key))
|
||||||
actual := testDB.Exec(nil, utils.ToCmdLine("GET", key))
|
actual := testDB.Exec(nil, utils.ToCmdLine("GET", key))
|
||||||
expected := reply.MakeBulkReply([]byte(strconv.FormatInt(int64(i+1), 10)))
|
expected := protocol.MakeBulkReply([]byte(strconv.FormatInt(int64(i+1), 10)))
|
||||||
if !utils.BytesEquals(actual.ToBytes(), expected.ToBytes()) {
|
if !utils.BytesEquals(actual.ToBytes(), expected.ToBytes()) {
|
||||||
t.Error("expected: " + string(expected.ToBytes()) + ", actual: " + string(actual.ToBytes()))
|
t.Error("expected: " + string(expected.ToBytes()) + ", actual: " + string(actual.ToBytes()))
|
||||||
}
|
}
|
||||||
@@ -214,7 +214,7 @@ func TestIncr(t *testing.T) {
|
|||||||
for i := 0; i < size; i++ {
|
for i := 0; i < size; i++ {
|
||||||
testDB.Exec(nil, utils.ToCmdLine("INCRBY", key, "-1"))
|
testDB.Exec(nil, utils.ToCmdLine("INCRBY", key, "-1"))
|
||||||
actual := testDB.Exec(nil, utils.ToCmdLine("GET", key))
|
actual := testDB.Exec(nil, utils.ToCmdLine("GET", key))
|
||||||
expected := reply.MakeBulkReply([]byte(strconv.FormatInt(int64(size-i-1), 10)))
|
expected := protocol.MakeBulkReply([]byte(strconv.FormatInt(int64(size-i-1), 10)))
|
||||||
if !utils.BytesEquals(actual.ToBytes(), expected.ToBytes()) {
|
if !utils.BytesEquals(actual.ToBytes(), expected.ToBytes()) {
|
||||||
t.Error("expected: " + string(expected.ToBytes()) + ", actual: " + string(actual.ToBytes()))
|
t.Error("expected: " + string(expected.ToBytes()) + ", actual: " + string(actual.ToBytes()))
|
||||||
}
|
}
|
||||||
@@ -225,7 +225,7 @@ func TestIncr(t *testing.T) {
|
|||||||
for i := 0; i < size; i++ {
|
for i := 0; i < size; i++ {
|
||||||
testDB.Exec(nil, utils.ToCmdLine("INCRBY", key, "1"))
|
testDB.Exec(nil, utils.ToCmdLine("INCRBY", key, "1"))
|
||||||
actual := testDB.Exec(nil, utils.ToCmdLine("GET", key))
|
actual := testDB.Exec(nil, utils.ToCmdLine("GET", key))
|
||||||
expected := reply.MakeBulkReply([]byte(strconv.FormatInt(int64(i+1), 10)))
|
expected := protocol.MakeBulkReply([]byte(strconv.FormatInt(int64(i+1), 10)))
|
||||||
if !utils.BytesEquals(actual.ToBytes(), expected.ToBytes()) {
|
if !utils.BytesEquals(actual.ToBytes(), expected.ToBytes()) {
|
||||||
t.Error("expected: " + string(expected.ToBytes()) + ", actual: " + string(actual.ToBytes()))
|
t.Error("expected: " + string(expected.ToBytes()) + ", actual: " + string(actual.ToBytes()))
|
||||||
}
|
}
|
||||||
@@ -235,9 +235,9 @@ func TestIncr(t *testing.T) {
|
|||||||
testDB.Exec(nil, utils.ToCmdLine("INCRBYFLOAT", key, "-1.0"))
|
testDB.Exec(nil, utils.ToCmdLine("INCRBYFLOAT", key, "-1.0"))
|
||||||
actual := testDB.Exec(nil, utils.ToCmdLine("GET", key))
|
actual := testDB.Exec(nil, utils.ToCmdLine("GET", key))
|
||||||
expected := -i - 1
|
expected := -i - 1
|
||||||
bulk, ok := actual.(*reply.BulkReply)
|
bulk, ok := actual.(*protocol.BulkReply)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Error(fmt.Sprintf("expected bulk reply, actually %s", actual.ToBytes()))
|
t.Error(fmt.Sprintf("expected bulk protocol, actually %s", actual.ToBytes()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val, err := strconv.ParseFloat(string(bulk.Arg), 10)
|
val, err := strconv.ParseFloat(string(bulk.Arg), 10)
|
||||||
@@ -266,9 +266,9 @@ func TestDecr(t *testing.T) {
|
|||||||
testDB.Exec(nil, utils.ToCmdLine("DECRBY", key, "1"))
|
testDB.Exec(nil, utils.ToCmdLine("DECRBY", key, "1"))
|
||||||
actual := testDB.Exec(nil, utils.ToCmdLine("GET", key))
|
actual := testDB.Exec(nil, utils.ToCmdLine("GET", key))
|
||||||
expected := -i - 1
|
expected := -i - 1
|
||||||
bulk, ok := actual.(*reply.BulkReply)
|
bulk, ok := actual.(*protocol.BulkReply)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Error(fmt.Sprintf("expected bulk reply, actually %s", actual.ToBytes()))
|
t.Error(fmt.Sprintf("expected bulk protocol, actually %s", actual.ToBytes()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val, err := strconv.ParseFloat(string(bulk.Arg), 10)
|
val, err := strconv.ParseFloat(string(bulk.Arg), 10)
|
||||||
@@ -289,9 +289,9 @@ func TestGetSet(t *testing.T) {
|
|||||||
value := utils.RandString(10)
|
value := utils.RandString(10)
|
||||||
|
|
||||||
actual := testDB.Exec(nil, utils.ToCmdLine("GETSET", key, value))
|
actual := testDB.Exec(nil, utils.ToCmdLine("GETSET", key, value))
|
||||||
_, ok := actual.(*reply.NullBulkReply)
|
_, ok := actual.(*protocol.NullBulkReply)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Errorf("expect null bulk reply, get: %s", string(actual.ToBytes()))
|
t.Errorf("expect null bulk protocol, get: %s", string(actual.ToBytes()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -323,9 +323,9 @@ func TestStrLen(t *testing.T) {
|
|||||||
testDB.Exec(nil, utils.ToCmdLine2("SET", key, key))
|
testDB.Exec(nil, utils.ToCmdLine2("SET", key, key))
|
||||||
|
|
||||||
actual := testDB.Exec(nil, utils.ToCmdLine("StrLen", key))
|
actual := testDB.Exec(nil, utils.ToCmdLine("StrLen", key))
|
||||||
len, ok := actual.(*reply.IntReply)
|
len, ok := actual.(*protocol.IntReply)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Errorf("expect int bulk reply, get: %s", string(actual.ToBytes()))
|
t.Errorf("expect int bulk protocol, get: %s", string(actual.ToBytes()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
asserts.AssertIntReply(t, len, 10)
|
asserts.AssertIntReply(t, len, 10)
|
||||||
@@ -336,9 +336,9 @@ func TestStrLen_KeyNotExist(t *testing.T) {
|
|||||||
key := utils.RandString(10)
|
key := utils.RandString(10)
|
||||||
|
|
||||||
actual := testDB.Exec(nil, utils.ToCmdLine("StrLen", key))
|
actual := testDB.Exec(nil, utils.ToCmdLine("StrLen", key))
|
||||||
result, ok := actual.(*reply.IntReply)
|
result, ok := actual.(*protocol.IntReply)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Errorf("expect null bulk reply, get: %s", string(actual.ToBytes()))
|
t.Errorf("expect null bulk protocol, get: %s", string(actual.ToBytes()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -352,9 +352,9 @@ func TestAppend_KeyExist(t *testing.T) {
|
|||||||
testDB.Exec(nil, utils.ToCmdLine2("SET", key, key))
|
testDB.Exec(nil, utils.ToCmdLine2("SET", key, key))
|
||||||
|
|
||||||
actual := testDB.Exec(nil, utils.ToCmdLine("Append", key, key2))
|
actual := testDB.Exec(nil, utils.ToCmdLine("Append", key, key2))
|
||||||
val, ok := actual.(*reply.IntReply)
|
val, ok := actual.(*protocol.IntReply)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Errorf("expect nil bulk reply, get: %s", string(actual.ToBytes()))
|
t.Errorf("expect nil bulk protocol, get: %s", string(actual.ToBytes()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
asserts.AssertIntReply(t, val, len(key)*2)
|
asserts.AssertIntReply(t, val, len(key)*2)
|
||||||
@@ -365,9 +365,9 @@ func TestAppend_KeyNotExist(t *testing.T) {
|
|||||||
key := utils.RandString(10)
|
key := utils.RandString(10)
|
||||||
|
|
||||||
actual := testDB.Exec(nil, utils.ToCmdLine("Append", key, key))
|
actual := testDB.Exec(nil, utils.ToCmdLine("Append", key, key))
|
||||||
val, ok := actual.(*reply.IntReply)
|
val, ok := actual.(*protocol.IntReply)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Errorf("expect nil bulk reply, get: %s", string(actual.ToBytes()))
|
t.Errorf("expect nil bulk protocol, get: %s", string(actual.ToBytes()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
asserts.AssertIntReply(t, val, len(key))
|
asserts.AssertIntReply(t, val, len(key))
|
||||||
@@ -380,9 +380,9 @@ func TestSetRange_StringExist(t *testing.T) {
|
|||||||
testDB.Exec(nil, utils.ToCmdLine2("SET", key, key))
|
testDB.Exec(nil, utils.ToCmdLine2("SET", key, key))
|
||||||
|
|
||||||
actual := testDB.Exec(nil, utils.ToCmdLine("SetRange", key, fmt.Sprint(0), key2))
|
actual := testDB.Exec(nil, utils.ToCmdLine("SetRange", key, fmt.Sprint(0), key2))
|
||||||
val, ok := actual.(*reply.IntReply)
|
val, ok := actual.(*protocol.IntReply)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Errorf("expect int bulk reply, get: %s", string(actual.ToBytes()))
|
t.Errorf("expect int bulk protocol, get: %s", string(actual.ToBytes()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -398,9 +398,9 @@ func TestSetRange_StringExist_OffsetOutOfLen(t *testing.T) {
|
|||||||
testDB.Exec(nil, utils.ToCmdLine2("SET", key, key))
|
testDB.Exec(nil, utils.ToCmdLine2("SET", key, key))
|
||||||
|
|
||||||
actual := testDB.Exec(nil, utils.ToCmdLine("SetRange", key, fmt.Sprint(len(key)+emptyByteLen), key2))
|
actual := testDB.Exec(nil, utils.ToCmdLine("SetRange", key, fmt.Sprint(len(key)+emptyByteLen), key2))
|
||||||
val, ok := actual.(*reply.IntReply)
|
val, ok := actual.(*protocol.IntReply)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Errorf("expect int bulk reply, get: %s", string(actual.ToBytes()))
|
t.Errorf("expect int bulk protocol, get: %s", string(actual.ToBytes()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -413,9 +413,9 @@ func TestSetRange_StringNotExist(t *testing.T) {
|
|||||||
key := utils.RandString(10)
|
key := utils.RandString(10)
|
||||||
|
|
||||||
actual := testDB.Exec(nil, utils.ToCmdLine("SetRange", key, fmt.Sprint(0), key))
|
actual := testDB.Exec(nil, utils.ToCmdLine("SetRange", key, fmt.Sprint(0), key))
|
||||||
val, ok := actual.(*reply.IntReply)
|
val, ok := actual.(*protocol.IntReply)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Errorf("expect int bulk reply, get: %s", string(actual.ToBytes()))
|
t.Errorf("expect int bulk protocol, get: %s", string(actual.ToBytes()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
asserts.AssertIntReply(t, val, len(key))
|
asserts.AssertIntReply(t, val, len(key))
|
||||||
@@ -427,9 +427,9 @@ func TestGetRange_StringExist(t *testing.T) {
|
|||||||
testDB.Exec(nil, utils.ToCmdLine2("SET", key, key))
|
testDB.Exec(nil, utils.ToCmdLine2("SET", key, key))
|
||||||
|
|
||||||
actual := testDB.Exec(nil, utils.ToCmdLine("GetRange", key, fmt.Sprint(0), fmt.Sprint(len(key))))
|
actual := testDB.Exec(nil, utils.ToCmdLine("GetRange", key, fmt.Sprint(0), fmt.Sprint(len(key))))
|
||||||
val, ok := actual.(*reply.BulkReply)
|
val, ok := actual.(*protocol.BulkReply)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Errorf("expect bulk reply, get: %s", string(actual.ToBytes()))
|
t.Errorf("expect bulk protocol, get: %s", string(actual.ToBytes()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -442,9 +442,9 @@ func TestGetRange_RangeLargeThenDataLen(t *testing.T) {
|
|||||||
testDB.Exec(nil, utils.ToCmdLine2("SET", key, key))
|
testDB.Exec(nil, utils.ToCmdLine2("SET", key, key))
|
||||||
|
|
||||||
actual := testDB.Exec(nil, utils.ToCmdLine("GetRange", key, fmt.Sprint(0), fmt.Sprint(len(key)+2)))
|
actual := testDB.Exec(nil, utils.ToCmdLine("GetRange", key, fmt.Sprint(0), fmt.Sprint(len(key)+2)))
|
||||||
val, ok := actual.(*reply.BulkReply)
|
val, ok := actual.(*protocol.BulkReply)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Errorf("expect bulk reply, get: %s", string(actual.ToBytes()))
|
t.Errorf("expect bulk protocol, get: %s", string(actual.ToBytes()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -455,9 +455,9 @@ func TestGetRange_StringNotExist(t *testing.T) {
|
|||||||
testDB.Flush()
|
testDB.Flush()
|
||||||
key := utils.RandString(10)
|
key := utils.RandString(10)
|
||||||
actual := testDB.Exec(nil, utils.ToCmdLine("GetRange", key, fmt.Sprint(0), fmt.Sprint(len(key))))
|
actual := testDB.Exec(nil, utils.ToCmdLine("GetRange", key, fmt.Sprint(0), fmt.Sprint(len(key))))
|
||||||
val, ok := actual.(*reply.NullBulkReply)
|
val, ok := actual.(*protocol.NullBulkReply)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Errorf("expect nil bulk reply, get: %s", string(actual.ToBytes()))
|
t.Errorf("expect nil bulk protocol, get: %s", string(actual.ToBytes()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -470,9 +470,9 @@ func TestGetRange_StringExist_GetPartial(t *testing.T) {
|
|||||||
testDB.Exec(nil, utils.ToCmdLine2("SET", key, key))
|
testDB.Exec(nil, utils.ToCmdLine2("SET", key, key))
|
||||||
|
|
||||||
actual := testDB.Exec(nil, utils.ToCmdLine("GetRange", key, fmt.Sprint(0), fmt.Sprint(len(key)/2)))
|
actual := testDB.Exec(nil, utils.ToCmdLine("GetRange", key, fmt.Sprint(0), fmt.Sprint(len(key)/2)))
|
||||||
val, ok := actual.(*reply.BulkReply)
|
val, ok := actual.(*protocol.BulkReply)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Errorf("expect bulk reply, get: %s", string(actual.ToBytes()))
|
t.Errorf("expect bulk protocol, get: %s", string(actual.ToBytes()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -486,9 +486,9 @@ func TestGetRange_StringExist_EndIdxOutOfRange(t *testing.T) {
|
|||||||
testDB.Exec(nil, utils.ToCmdLine2("SET", key, key))
|
testDB.Exec(nil, utils.ToCmdLine2("SET", key, key))
|
||||||
|
|
||||||
actual := testDB.Exec(nil, utils.ToCmdLine("GetRange", key, fmt.Sprint(0), fmt.Sprint(len(key)+emptyByteLen)))
|
actual := testDB.Exec(nil, utils.ToCmdLine("GetRange", key, fmt.Sprint(0), fmt.Sprint(len(key)+emptyByteLen)))
|
||||||
val, ok := actual.(*reply.BulkReply)
|
val, ok := actual.(*protocol.BulkReply)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Errorf("expect bulk reply, get: %s", string(actual.ToBytes()))
|
t.Errorf("expect bulk protocol, get: %s", string(actual.ToBytes()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -502,9 +502,9 @@ func TestGetRange_StringExist_StartIdxEndIdxAreSame(t *testing.T) {
|
|||||||
testDB.Exec(nil, utils.ToCmdLine2("SET", key, key))
|
testDB.Exec(nil, utils.ToCmdLine2("SET", key, key))
|
||||||
|
|
||||||
actual := testDB.Exec(nil, utils.ToCmdLine("GetRange", key, fmt.Sprint(len(key)+emptyByteLen), fmt.Sprint(len(key)+emptyByteLen)))
|
actual := testDB.Exec(nil, utils.ToCmdLine("GetRange", key, fmt.Sprint(len(key)+emptyByteLen), fmt.Sprint(len(key)+emptyByteLen)))
|
||||||
val, ok := actual.(*reply.NullBulkReply)
|
val, ok := actual.(*protocol.NullBulkReply)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Errorf("expect nil bulk reply, get: %s", string(actual.ToBytes()))
|
t.Errorf("expect nil bulk protocol, get: %s", string(actual.ToBytes()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -516,9 +516,9 @@ func TestGetRange_StringExist_StartIdxGreaterThanEndIdx(t *testing.T) {
|
|||||||
key := utils.RandString(10)
|
key := utils.RandString(10)
|
||||||
|
|
||||||
actual := testDB.Exec(nil, utils.ToCmdLine("GetRange", key, fmt.Sprint(len(key)+1), fmt.Sprint(len(key))))
|
actual := testDB.Exec(nil, utils.ToCmdLine("GetRange", key, fmt.Sprint(len(key)+1), fmt.Sprint(len(key))))
|
||||||
val, ok := actual.(*reply.NullBulkReply)
|
val, ok := actual.(*protocol.NullBulkReply)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Errorf("expect nil bulk reply, get: %s", string(actual.ToBytes()))
|
t.Errorf("expect nil bulk protocol, get: %s", string(actual.ToBytes()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -531,9 +531,9 @@ func TestGetRange_StringExist_StartIdxEndIdxAreNegative(t *testing.T) {
|
|||||||
testDB.Exec(nil, utils.ToCmdLine2("SET", key, key))
|
testDB.Exec(nil, utils.ToCmdLine2("SET", key, key))
|
||||||
|
|
||||||
actual := testDB.Exec(nil, utils.ToCmdLine("GetRange", key, fmt.Sprint(-1*len(key)), fmt.Sprint(-1)))
|
actual := testDB.Exec(nil, utils.ToCmdLine("GetRange", key, fmt.Sprint(-1*len(key)), fmt.Sprint(-1)))
|
||||||
val, ok := actual.(*reply.BulkReply)
|
val, ok := actual.(*protocol.BulkReply)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Errorf("expect bulk reply, get: %s", string(actual.ToBytes()))
|
t.Errorf("expect bulk protocol, get: %s", string(actual.ToBytes()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -546,9 +546,9 @@ func TestGetRange_StringExist_StartIdxNegative(t *testing.T) {
|
|||||||
testDB.Exec(nil, utils.ToCmdLine2("SET", key, key))
|
testDB.Exec(nil, utils.ToCmdLine2("SET", key, key))
|
||||||
|
|
||||||
actual := testDB.Exec(nil, utils.ToCmdLine("GetRange", key, fmt.Sprint(-1*len(key)), fmt.Sprint(len(key)/2)))
|
actual := testDB.Exec(nil, utils.ToCmdLine("GetRange", key, fmt.Sprint(-1*len(key)), fmt.Sprint(len(key)/2)))
|
||||||
val, ok := actual.(*reply.BulkReply)
|
val, ok := actual.(*protocol.BulkReply)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Errorf("expect bulk reply, get: %s", string(actual.ToBytes()))
|
t.Errorf("expect bulk protocol, get: %s", string(actual.ToBytes()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -561,9 +561,9 @@ func TestGetRange_StringExist_EndIdxNegative(t *testing.T) {
|
|||||||
testDB.Exec(nil, utils.ToCmdLine2("SET", key, key))
|
testDB.Exec(nil, utils.ToCmdLine2("SET", key, key))
|
||||||
|
|
||||||
actual := testDB.Exec(nil, utils.ToCmdLine("GetRange", key, fmt.Sprint(0), fmt.Sprint(-len(key)/2)))
|
actual := testDB.Exec(nil, utils.ToCmdLine("GetRange", key, fmt.Sprint(0), fmt.Sprint(-len(key)/2)))
|
||||||
val, ok := actual.(*reply.BulkReply)
|
val, ok := actual.(*protocol.BulkReply)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Errorf("expect bulk reply, get: %s", string(actual.ToBytes()))
|
t.Errorf("expect bulk protocol, get: %s", string(actual.ToBytes()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -576,9 +576,9 @@ func TestGetRange_StringExist_StartIsOutOfRange(t *testing.T) {
|
|||||||
testDB.Exec(nil, utils.ToCmdLine2("SET", key, key))
|
testDB.Exec(nil, utils.ToCmdLine2("SET", key, key))
|
||||||
|
|
||||||
actual := testDB.Exec(nil, utils.ToCmdLine("GetRange", key, fmt.Sprint(-len(key)-3), fmt.Sprint(len(key))))
|
actual := testDB.Exec(nil, utils.ToCmdLine("GetRange", key, fmt.Sprint(-len(key)-3), fmt.Sprint(len(key))))
|
||||||
val, ok := actual.(*reply.NullBulkReply)
|
val, ok := actual.(*protocol.NullBulkReply)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Errorf("expect bulk reply, get: %s", string(actual.ToBytes()))
|
t.Errorf("expect bulk protocol, get: %s", string(actual.ToBytes()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -591,9 +591,9 @@ func TestGetRange_StringExist_EndIdxIsOutOfRange(t *testing.T) {
|
|||||||
testDB.Exec(nil, utils.ToCmdLine2("SET", key, key))
|
testDB.Exec(nil, utils.ToCmdLine2("SET", key, key))
|
||||||
|
|
||||||
actual := testDB.Exec(nil, utils.ToCmdLine("GetRange", key, fmt.Sprint(0), fmt.Sprint(-len(key)-3)))
|
actual := testDB.Exec(nil, utils.ToCmdLine("GetRange", key, fmt.Sprint(0), fmt.Sprint(-len(key)-3)))
|
||||||
val, ok := actual.(*reply.NullBulkReply)
|
val, ok := actual.(*protocol.NullBulkReply)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Errorf("expect bulk reply, get: %s", string(actual.ToBytes()))
|
t.Errorf("expect bulk protocol, get: %s", string(actual.ToBytes()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -606,9 +606,9 @@ func TestGetRange_StringExist_StartIdxGreaterThanDataLen(t *testing.T) {
|
|||||||
testDB.Exec(nil, utils.ToCmdLine2("SET", key, key))
|
testDB.Exec(nil, utils.ToCmdLine2("SET", key, key))
|
||||||
|
|
||||||
actual := testDB.Exec(nil, utils.ToCmdLine("GetRange", key, fmt.Sprint(len(key)+1), fmt.Sprint(0)))
|
actual := testDB.Exec(nil, utils.ToCmdLine("GetRange", key, fmt.Sprint(len(key)+1), fmt.Sprint(0)))
|
||||||
val, ok := actual.(*reply.NullBulkReply)
|
val, ok := actual.(*protocol.NullBulkReply)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Errorf("expect bulk reply, get: %s", string(actual.ToBytes()))
|
t.Errorf("expect bulk protocol, get: %s", string(actual.ToBytes()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -622,9 +622,9 @@ func TestGetRange_StringExist_StartIdxIncorrectFormat(t *testing.T) {
|
|||||||
incorrectValue := "incorrect"
|
incorrectValue := "incorrect"
|
||||||
|
|
||||||
actual := testDB.Exec(nil, utils.ToCmdLine("GetRange", key, incorrectValue, fmt.Sprint(0)))
|
actual := testDB.Exec(nil, utils.ToCmdLine("GetRange", key, incorrectValue, fmt.Sprint(0)))
|
||||||
val, ok := actual.(*reply.StandardErrReply)
|
val, ok := actual.(*protocol.StandardErrReply)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Errorf("expect standart bulk reply, get: %s", string(actual.ToBytes()))
|
t.Errorf("expect standart bulk protocol, get: %s", string(actual.ToBytes()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -639,9 +639,9 @@ func TestGetRange_StringExist_EndIdxIncorrectFormat(t *testing.T) {
|
|||||||
incorrectValue := "incorrect"
|
incorrectValue := "incorrect"
|
||||||
|
|
||||||
actual := testDB.Exec(nil, utils.ToCmdLine("GetRange", key, fmt.Sprint(0), incorrectValue))
|
actual := testDB.Exec(nil, utils.ToCmdLine("GetRange", key, fmt.Sprint(0), incorrectValue))
|
||||||
val, ok := actual.(*reply.StandardErrReply)
|
val, ok := actual.(*protocol.StandardErrReply)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Errorf("expect standart bulk reply, get: %s", string(actual.ToBytes()))
|
t.Errorf("expect standart bulk protocol, get: %s", string(actual.ToBytes()))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -3,34 +3,34 @@ package database
|
|||||||
import (
|
import (
|
||||||
"github.com/hdt3213/godis/config"
|
"github.com/hdt3213/godis/config"
|
||||||
"github.com/hdt3213/godis/interface/redis"
|
"github.com/hdt3213/godis/interface/redis"
|
||||||
"github.com/hdt3213/godis/redis/reply"
|
"github.com/hdt3213/godis/redis/protocol"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Ping the server
|
// Ping the server
|
||||||
func Ping(db *DB, args [][]byte) redis.Reply {
|
func Ping(db *DB, args [][]byte) redis.Reply {
|
||||||
if len(args) == 0 {
|
if len(args) == 0 {
|
||||||
return &reply.PongReply{}
|
return &protocol.PongReply{}
|
||||||
} else if len(args) == 1 {
|
} else if len(args) == 1 {
|
||||||
return reply.MakeStatusReply(string(args[0]))
|
return protocol.MakeStatusReply(string(args[0]))
|
||||||
} else {
|
} else {
|
||||||
return reply.MakeErrReply("ERR wrong number of arguments for 'ping' command")
|
return protocol.MakeErrReply("ERR wrong number of arguments for 'ping' command")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Auth validate client's password
|
// Auth validate client's password
|
||||||
func Auth(c redis.Connection, args [][]byte) redis.Reply {
|
func Auth(c redis.Connection, args [][]byte) redis.Reply {
|
||||||
if len(args) != 1 {
|
if len(args) != 1 {
|
||||||
return reply.MakeErrReply("ERR wrong number of arguments for 'auth' command")
|
return protocol.MakeErrReply("ERR wrong number of arguments for 'auth' command")
|
||||||
}
|
}
|
||||||
if config.Properties.RequirePass == "" {
|
if config.Properties.RequirePass == "" {
|
||||||
return reply.MakeErrReply("ERR Client sent AUTH, but no password is set")
|
return protocol.MakeErrReply("ERR Client sent AUTH, but no password is set")
|
||||||
}
|
}
|
||||||
passwd := string(args[0])
|
passwd := string(args[0])
|
||||||
c.SetPassword(passwd)
|
c.SetPassword(passwd)
|
||||||
if config.Properties.RequirePass != passwd {
|
if config.Properties.RequirePass != passwd {
|
||||||
return reply.MakeErrReply("ERR invalid password")
|
return protocol.MakeErrReply("ERR invalid password")
|
||||||
}
|
}
|
||||||
return &reply.OkReply{}
|
return &protocol.OkReply{}
|
||||||
}
|
}
|
||||||
|
|
||||||
func isAuthenticated(c redis.Connection) bool {
|
func isAuthenticated(c redis.Connection) bool {
|
||||||
|
@@ -4,7 +4,7 @@ import (
|
|||||||
"github.com/hdt3213/godis/config"
|
"github.com/hdt3213/godis/config"
|
||||||
"github.com/hdt3213/godis/lib/utils"
|
"github.com/hdt3213/godis/lib/utils"
|
||||||
"github.com/hdt3213/godis/redis/connection"
|
"github.com/hdt3213/godis/redis/connection"
|
||||||
"github.com/hdt3213/godis/redis/reply/asserts"
|
"github.com/hdt3213/godis/redis/protocol/asserts"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -3,7 +3,7 @@ package database
|
|||||||
import (
|
import (
|
||||||
"github.com/hdt3213/godis/datastruct/set"
|
"github.com/hdt3213/godis/datastruct/set"
|
||||||
"github.com/hdt3213/godis/interface/redis"
|
"github.com/hdt3213/godis/interface/redis"
|
||||||
"github.com/hdt3213/godis/redis/reply"
|
"github.com/hdt3213/godis/redis/protocol"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -19,13 +19,13 @@ func Watch(db *DB, conn redis.Connection, args [][]byte) redis.Reply {
|
|||||||
key := string(bkey)
|
key := string(bkey)
|
||||||
watching[key] = db.GetVersion(key)
|
watching[key] = db.GetVersion(key)
|
||||||
}
|
}
|
||||||
return reply.MakeOkReply()
|
return protocol.MakeOkReply()
|
||||||
}
|
}
|
||||||
|
|
||||||
func execGetVersion(db *DB, args [][]byte) redis.Reply {
|
func execGetVersion(db *DB, args [][]byte) redis.Reply {
|
||||||
key := string(args[0])
|
key := string(args[0])
|
||||||
ver := db.GetVersion(key)
|
ver := db.GetVersion(key)
|
||||||
return reply.MakeIntReply(int64(ver))
|
return protocol.MakeIntReply(int64(ver))
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@@ -46,10 +46,10 @@ func isWatchingChanged(db *DB, watching map[string]uint32) bool {
|
|||||||
// StartMulti starts multi-command-transaction
|
// StartMulti starts multi-command-transaction
|
||||||
func StartMulti(conn redis.Connection) redis.Reply {
|
func StartMulti(conn redis.Connection) redis.Reply {
|
||||||
if conn.InMultiState() {
|
if conn.InMultiState() {
|
||||||
return reply.MakeErrReply("ERR MULTI calls can not be nested")
|
return protocol.MakeErrReply("ERR MULTI calls can not be nested")
|
||||||
}
|
}
|
||||||
conn.SetMultiState(true)
|
conn.SetMultiState(true)
|
||||||
return reply.MakeOkReply()
|
return protocol.MakeOkReply()
|
||||||
}
|
}
|
||||||
|
|
||||||
// EnqueueCmd puts command line into `multi` pending queue
|
// EnqueueCmd puts command line into `multi` pending queue
|
||||||
@@ -57,25 +57,25 @@ func EnqueueCmd(conn redis.Connection, cmdLine [][]byte) redis.Reply {
|
|||||||
cmdName := strings.ToLower(string(cmdLine[0]))
|
cmdName := strings.ToLower(string(cmdLine[0]))
|
||||||
cmd, ok := cmdTable[cmdName]
|
cmd, ok := cmdTable[cmdName]
|
||||||
if !ok {
|
if !ok {
|
||||||
return reply.MakeErrReply("ERR unknown command '" + cmdName + "'")
|
return protocol.MakeErrReply("ERR unknown command '" + cmdName + "'")
|
||||||
}
|
}
|
||||||
if forbiddenInMulti.Has(cmdName) {
|
if forbiddenInMulti.Has(cmdName) {
|
||||||
return reply.MakeErrReply("ERR command '" + cmdName + "' cannot be used in MULTI")
|
return protocol.MakeErrReply("ERR command '" + cmdName + "' cannot be used in MULTI")
|
||||||
}
|
}
|
||||||
if cmd.prepare == nil {
|
if cmd.prepare == nil {
|
||||||
return reply.MakeErrReply("ERR command '" + cmdName + "' cannot be used in MULTI")
|
return protocol.MakeErrReply("ERR command '" + cmdName + "' cannot be used in MULTI")
|
||||||
}
|
}
|
||||||
if !validateArity(cmd.arity, cmdLine) {
|
if !validateArity(cmd.arity, cmdLine) {
|
||||||
// difference with redis: we won't enqueue command line with wrong arity
|
// difference with redis: we won't enqueue command line with wrong arity
|
||||||
return reply.MakeArgNumErrReply(cmdName)
|
return protocol.MakeArgNumErrReply(cmdName)
|
||||||
}
|
}
|
||||||
conn.EnqueueCmd(cmdLine)
|
conn.EnqueueCmd(cmdLine)
|
||||||
return reply.MakeQueuedReply()
|
return protocol.MakeQueuedReply()
|
||||||
}
|
}
|
||||||
|
|
||||||
func execMulti(db *DB, conn redis.Connection) redis.Reply {
|
func execMulti(db *DB, conn redis.Connection) redis.Reply {
|
||||||
if !conn.InMultiState() {
|
if !conn.InMultiState() {
|
||||||
return reply.MakeErrReply("ERR EXEC without MULTI")
|
return protocol.MakeErrReply("ERR EXEC without MULTI")
|
||||||
}
|
}
|
||||||
defer conn.SetMultiState(false)
|
defer conn.SetMultiState(false)
|
||||||
cmdLines := conn.GetQueuedCmdLine()
|
cmdLines := conn.GetQueuedCmdLine()
|
||||||
@@ -105,7 +105,7 @@ func (db *DB) ExecMulti(conn redis.Connection, watching map[string]uint32, cmdLi
|
|||||||
defer db.RWUnLocks(writeKeys, readKeys)
|
defer db.RWUnLocks(writeKeys, readKeys)
|
||||||
|
|
||||||
if isWatchingChanged(db, watching) { // watching keys changed, abort
|
if isWatchingChanged(db, watching) { // watching keys changed, abort
|
||||||
return reply.MakeEmptyMultiBulkReply()
|
return protocol.MakeEmptyMultiBulkReply()
|
||||||
}
|
}
|
||||||
// execute
|
// execute
|
||||||
results := make([]redis.Reply, 0, len(cmdLines))
|
results := make([]redis.Reply, 0, len(cmdLines))
|
||||||
@@ -114,7 +114,7 @@ func (db *DB) ExecMulti(conn redis.Connection, watching map[string]uint32, cmdLi
|
|||||||
for _, cmdLine := range cmdLines {
|
for _, cmdLine := range cmdLines {
|
||||||
undoCmdLines = append(undoCmdLines, db.GetUndoLogs(cmdLine))
|
undoCmdLines = append(undoCmdLines, db.GetUndoLogs(cmdLine))
|
||||||
result := db.execWithLock(cmdLine)
|
result := db.execWithLock(cmdLine)
|
||||||
if reply.IsErrorReply(result) {
|
if protocol.IsErrorReply(result) {
|
||||||
aborted = true
|
aborted = true
|
||||||
// don't rollback failed commands
|
// don't rollback failed commands
|
||||||
undoCmdLines = undoCmdLines[:len(undoCmdLines)-1]
|
undoCmdLines = undoCmdLines[:len(undoCmdLines)-1]
|
||||||
@@ -124,7 +124,7 @@ func (db *DB) ExecMulti(conn redis.Connection, watching map[string]uint32, cmdLi
|
|||||||
}
|
}
|
||||||
if !aborted { //success
|
if !aborted { //success
|
||||||
db.addVersion(writeKeys...)
|
db.addVersion(writeKeys...)
|
||||||
return reply.MakeMultiRawReply(results)
|
return protocol.MakeMultiRawReply(results)
|
||||||
}
|
}
|
||||||
// undo if aborted
|
// undo if aborted
|
||||||
size := len(undoCmdLines)
|
size := len(undoCmdLines)
|
||||||
@@ -137,17 +137,17 @@ func (db *DB) ExecMulti(conn redis.Connection, watching map[string]uint32, cmdLi
|
|||||||
db.execWithLock(cmdLine)
|
db.execWithLock(cmdLine)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return reply.MakeErrReply("EXECABORT Transaction discarded because of previous errors.")
|
return protocol.MakeErrReply("EXECABORT Transaction discarded because of previous errors.")
|
||||||
}
|
}
|
||||||
|
|
||||||
// DiscardMulti drops MULTI pending commands
|
// DiscardMulti drops MULTI pending commands
|
||||||
func DiscardMulti(conn redis.Connection) redis.Reply {
|
func DiscardMulti(conn redis.Connection) redis.Reply {
|
||||||
if !conn.InMultiState() {
|
if !conn.InMultiState() {
|
||||||
return reply.MakeErrReply("ERR DISCARD without MULTI")
|
return protocol.MakeErrReply("ERR DISCARD without MULTI")
|
||||||
}
|
}
|
||||||
conn.ClearQueuedCmds()
|
conn.ClearQueuedCmds()
|
||||||
conn.SetMultiState(false)
|
conn.SetMultiState(false)
|
||||||
return reply.MakeOkReply()
|
return protocol.MakeOkReply()
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetUndoLogs return rollback commands
|
// GetUndoLogs return rollback commands
|
||||||
@@ -169,10 +169,10 @@ func (db *DB) execWithLock(cmdLine [][]byte) redis.Reply {
|
|||||||
cmdName := strings.ToLower(string(cmdLine[0]))
|
cmdName := strings.ToLower(string(cmdLine[0]))
|
||||||
cmd, ok := cmdTable[cmdName]
|
cmd, ok := cmdTable[cmdName]
|
||||||
if !ok {
|
if !ok {
|
||||||
return reply.MakeErrReply("ERR unknown command '" + cmdName + "'")
|
return protocol.MakeErrReply("ERR unknown command '" + cmdName + "'")
|
||||||
}
|
}
|
||||||
if !validateArity(cmd.arity, cmdLine) {
|
if !validateArity(cmd.arity, cmdLine) {
|
||||||
return reply.MakeArgNumErrReply(cmdName)
|
return protocol.MakeArgNumErrReply(cmdName)
|
||||||
}
|
}
|
||||||
fun := cmd.executor
|
fun := cmd.executor
|
||||||
return fun(db, cmdLine[1:])
|
return fun(db, cmdLine[1:])
|
||||||
|
@@ -3,7 +3,7 @@ package database
|
|||||||
import (
|
import (
|
||||||
"github.com/hdt3213/godis/lib/utils"
|
"github.com/hdt3213/godis/lib/utils"
|
||||||
"github.com/hdt3213/godis/redis/connection"
|
"github.com/hdt3213/godis/redis/connection"
|
||||||
"github.com/hdt3213/godis/redis/reply/asserts"
|
"github.com/hdt3213/godis/redis/protocol/asserts"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -2,7 +2,7 @@ package database
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/hdt3213/godis/lib/utils"
|
"github.com/hdt3213/godis/lib/utils"
|
||||||
"github.com/hdt3213/godis/redis/reply/asserts"
|
"github.com/hdt3213/godis/redis/protocol/asserts"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
@@ -3,7 +3,7 @@ package pubsub
|
|||||||
import (
|
import (
|
||||||
"github.com/hdt3213/godis/datastruct/list"
|
"github.com/hdt3213/godis/datastruct/list"
|
||||||
"github.com/hdt3213/godis/interface/redis"
|
"github.com/hdt3213/godis/interface/redis"
|
||||||
"github.com/hdt3213/godis/redis/reply"
|
"github.com/hdt3213/godis/redis/protocol"
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -15,9 +15,9 @@ var (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func makeMsg(t string, channel string, code int64) []byte {
|
func makeMsg(t string, channel string, code int64) []byte {
|
||||||
return []byte("*3\r\n$" + strconv.FormatInt(int64(len(t)), 10) + reply.CRLF + t + reply.CRLF +
|
return []byte("*3\r\n$" + strconv.FormatInt(int64(len(t)), 10) + protocol.CRLF + t + protocol.CRLF +
|
||||||
"$" + strconv.FormatInt(int64(len(channel)), 10) + reply.CRLF + channel + reply.CRLF +
|
"$" + strconv.FormatInt(int64(len(channel)), 10) + protocol.CRLF + channel + protocol.CRLF +
|
||||||
":" + strconv.FormatInt(code, 10) + reply.CRLF)
|
":" + strconv.FormatInt(code, 10) + protocol.CRLF)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -80,7 +80,7 @@ func Subscribe(hub *Hub, c redis.Connection, args [][]byte) redis.Reply {
|
|||||||
_ = c.Write(makeMsg(_subscribe, channel, int64(c.SubsCount())))
|
_ = c.Write(makeMsg(_subscribe, channel, int64(c.SubsCount())))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return &reply.NoReply{}
|
return &protocol.NoReply{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// UnsubscribeAll removes the given connection from all subscribing channel
|
// UnsubscribeAll removes the given connection from all subscribing channel
|
||||||
@@ -113,7 +113,7 @@ func UnSubscribe(db *Hub, c redis.Connection, args [][]byte) redis.Reply {
|
|||||||
|
|
||||||
if len(channels) == 0 {
|
if len(channels) == 0 {
|
||||||
_ = c.Write(unSubscribeNothing)
|
_ = c.Write(unSubscribeNothing)
|
||||||
return &reply.NoReply{}
|
return &protocol.NoReply{}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, channel := range channels {
|
for _, channel := range channels {
|
||||||
@@ -121,13 +121,13 @@ func UnSubscribe(db *Hub, c redis.Connection, args [][]byte) redis.Reply {
|
|||||||
_ = c.Write(makeMsg(_unsubscribe, channel, int64(c.SubsCount())))
|
_ = c.Write(makeMsg(_unsubscribe, channel, int64(c.SubsCount())))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return &reply.NoReply{}
|
return &protocol.NoReply{}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Publish send msg to all subscribing client
|
// Publish send msg to all subscribing client
|
||||||
func Publish(hub *Hub, args [][]byte) redis.Reply {
|
func Publish(hub *Hub, args [][]byte) redis.Reply {
|
||||||
if len(args) != 2 {
|
if len(args) != 2 {
|
||||||
return &reply.ArgNumErrReply{Cmd: "publish"}
|
return &protocol.ArgNumErrReply{Cmd: "publish"}
|
||||||
}
|
}
|
||||||
channel := string(args[0])
|
channel := string(args[0])
|
||||||
message := args[1]
|
message := args[1]
|
||||||
@@ -137,7 +137,7 @@ func Publish(hub *Hub, args [][]byte) redis.Reply {
|
|||||||
|
|
||||||
raw, ok := hub.subs.Get(channel)
|
raw, ok := hub.subs.Get(channel)
|
||||||
if !ok {
|
if !ok {
|
||||||
return reply.MakeIntReply(0)
|
return protocol.MakeIntReply(0)
|
||||||
}
|
}
|
||||||
subscribers, _ := raw.(*list.LinkedList)
|
subscribers, _ := raw.(*list.LinkedList)
|
||||||
subscribers.ForEach(func(i int, c interface{}) bool {
|
subscribers.ForEach(func(i int, c interface{}) bool {
|
||||||
@@ -146,8 +146,8 @@ func Publish(hub *Hub, args [][]byte) redis.Reply {
|
|||||||
replyArgs[0] = messageBytes
|
replyArgs[0] = messageBytes
|
||||||
replyArgs[1] = []byte(channel)
|
replyArgs[1] = []byte(channel)
|
||||||
replyArgs[2] = message
|
replyArgs[2] = message
|
||||||
_ = client.Write(reply.MakeMultiBulkReply(replyArgs).ToBytes())
|
_ = client.Write(protocol.MakeMultiBulkReply(replyArgs).ToBytes())
|
||||||
return true
|
return true
|
||||||
})
|
})
|
||||||
return reply.MakeIntReply(int64(subscribers.Len()))
|
return protocol.MakeIntReply(int64(subscribers.Len()))
|
||||||
}
|
}
|
||||||
|
@@ -5,7 +5,7 @@ import (
|
|||||||
"github.com/hdt3213/godis/lib/logger"
|
"github.com/hdt3213/godis/lib/logger"
|
||||||
"github.com/hdt3213/godis/lib/sync/wait"
|
"github.com/hdt3213/godis/lib/sync/wait"
|
||||||
"github.com/hdt3213/godis/redis/parser"
|
"github.com/hdt3213/godis/redis/parser"
|
||||||
"github.com/hdt3213/godis/redis/reply"
|
"github.com/hdt3213/godis/redis/protocol"
|
||||||
"net"
|
"net"
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
"sync"
|
"sync"
|
||||||
@@ -128,10 +128,10 @@ func (client *Client) Send(args [][]byte) redis.Reply {
|
|||||||
client.pendingReqs <- request
|
client.pendingReqs <- request
|
||||||
timeout := request.waiting.WaitWithTimeout(maxWait)
|
timeout := request.waiting.WaitWithTimeout(maxWait)
|
||||||
if timeout {
|
if timeout {
|
||||||
return reply.MakeErrReply("server time out")
|
return protocol.MakeErrReply("server time out")
|
||||||
}
|
}
|
||||||
if request.err != nil {
|
if request.err != nil {
|
||||||
return reply.MakeErrReply("request failed")
|
return protocol.MakeErrReply("request failed")
|
||||||
}
|
}
|
||||||
return request.reply
|
return request.reply
|
||||||
}
|
}
|
||||||
@@ -153,7 +153,7 @@ func (client *Client) doRequest(req *request) {
|
|||||||
if req == nil || len(req.args) == 0 {
|
if req == nil || len(req.args) == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
re := reply.MakeMultiBulkReply(req.args)
|
re := protocol.MakeMultiBulkReply(req.args)
|
||||||
bytes := re.ToBytes()
|
bytes := re.ToBytes()
|
||||||
_, err := client.conn.Write(bytes)
|
_, err := client.conn.Write(bytes)
|
||||||
i := 0
|
i := 0
|
||||||
@@ -193,7 +193,7 @@ func (client *Client) handleRead() error {
|
|||||||
ch := parser.ParseStream(client.conn)
|
ch := parser.ParseStream(client.conn)
|
||||||
for payload := range ch {
|
for payload := range ch {
|
||||||
if payload.Err != nil {
|
if payload.Err != nil {
|
||||||
client.finishRequest(reply.MakeErrReply(payload.Err.Error()))
|
client.finishRequest(protocol.MakeErrReply(payload.Err.Error()))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
client.finishRequest(payload.Data)
|
client.finishRequest(payload.Data)
|
||||||
|
@@ -2,7 +2,7 @@ package client
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/hdt3213/godis/lib/logger"
|
"github.com/hdt3213/godis/lib/logger"
|
||||||
"github.com/hdt3213/godis/redis/reply"
|
"github.com/hdt3213/godis/redis/protocol"
|
||||||
"strconv"
|
"strconv"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
@@ -23,7 +23,7 @@ func TestClient(t *testing.T) {
|
|||||||
result := client.Send([][]byte{
|
result := client.Send([][]byte{
|
||||||
[]byte("PING"),
|
[]byte("PING"),
|
||||||
})
|
})
|
||||||
if statusRet, ok := result.(*reply.StatusReply); ok {
|
if statusRet, ok := result.(*protocol.StatusReply); ok {
|
||||||
if statusRet.Status != "PONG" {
|
if statusRet.Status != "PONG" {
|
||||||
t.Error("`ping` failed, result: " + statusRet.Status)
|
t.Error("`ping` failed, result: " + statusRet.Status)
|
||||||
}
|
}
|
||||||
@@ -34,7 +34,7 @@ func TestClient(t *testing.T) {
|
|||||||
[]byte("a"),
|
[]byte("a"),
|
||||||
[]byte("a"),
|
[]byte("a"),
|
||||||
})
|
})
|
||||||
if statusRet, ok := result.(*reply.StatusReply); ok {
|
if statusRet, ok := result.(*protocol.StatusReply); ok {
|
||||||
if statusRet.Status != "OK" {
|
if statusRet.Status != "OK" {
|
||||||
t.Error("`set` failed, result: " + statusRet.Status)
|
t.Error("`set` failed, result: " + statusRet.Status)
|
||||||
}
|
}
|
||||||
@@ -44,7 +44,7 @@ func TestClient(t *testing.T) {
|
|||||||
[]byte("GET"),
|
[]byte("GET"),
|
||||||
[]byte("a"),
|
[]byte("a"),
|
||||||
})
|
})
|
||||||
if bulkRet, ok := result.(*reply.BulkReply); ok {
|
if bulkRet, ok := result.(*protocol.BulkReply); ok {
|
||||||
if string(bulkRet.Arg) != "a" {
|
if string(bulkRet.Arg) != "a" {
|
||||||
t.Error("`get` failed, result: " + string(bulkRet.Arg))
|
t.Error("`get` failed, result: " + string(bulkRet.Arg))
|
||||||
}
|
}
|
||||||
@@ -54,7 +54,7 @@ func TestClient(t *testing.T) {
|
|||||||
[]byte("DEL"),
|
[]byte("DEL"),
|
||||||
[]byte("a"),
|
[]byte("a"),
|
||||||
})
|
})
|
||||||
if intRet, ok := result.(*reply.IntReply); ok {
|
if intRet, ok := result.(*protocol.IntReply); ok {
|
||||||
if intRet.Code != 1 {
|
if intRet.Code != 1 {
|
||||||
t.Error("`del` failed, result: " + strconv.FormatInt(intRet.Code, 10))
|
t.Error("`del` failed, result: " + strconv.FormatInt(intRet.Code, 10))
|
||||||
}
|
}
|
||||||
@@ -65,7 +65,7 @@ func TestClient(t *testing.T) {
|
|||||||
[]byte("GET"),
|
[]byte("GET"),
|
||||||
[]byte("a"),
|
[]byte("a"),
|
||||||
})
|
})
|
||||||
if _, ok := result.(*reply.NullBulkReply); !ok {
|
if _, ok := result.(*protocol.NullBulkReply); !ok {
|
||||||
t.Error("`get` failed, result: " + string(result.ToBytes()))
|
t.Error("`get` failed, result: " + string(result.ToBytes()))
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,7 +81,7 @@ func TestClient(t *testing.T) {
|
|||||||
[]byte("2"),
|
[]byte("2"),
|
||||||
[]byte("c"),
|
[]byte("c"),
|
||||||
})
|
})
|
||||||
if intRet, ok := result.(*reply.IntReply); ok {
|
if intRet, ok := result.(*protocol.IntReply); ok {
|
||||||
if intRet.Code != 3 {
|
if intRet.Code != 3 {
|
||||||
t.Error("`rpush` failed, result: " + strconv.FormatInt(intRet.Code, 10))
|
t.Error("`rpush` failed, result: " + strconv.FormatInt(intRet.Code, 10))
|
||||||
}
|
}
|
||||||
@@ -93,7 +93,7 @@ func TestClient(t *testing.T) {
|
|||||||
[]byte("0"),
|
[]byte("0"),
|
||||||
[]byte("-1"),
|
[]byte("-1"),
|
||||||
})
|
})
|
||||||
if multiBulkRet, ok := result.(*reply.MultiBulkReply); ok {
|
if multiBulkRet, ok := result.(*protocol.MultiBulkReply); ok {
|
||||||
if len(multiBulkRet.Args) != 3 ||
|
if len(multiBulkRet.Args) != 3 ||
|
||||||
string(multiBulkRet.Args[0]) != "1" ||
|
string(multiBulkRet.Args[0]) != "1" ||
|
||||||
string(multiBulkRet.Args[1]) != "2" ||
|
string(multiBulkRet.Args[1]) != "2" ||
|
||||||
|
@@ -12,7 +12,7 @@ import (
|
|||||||
type Connection struct {
|
type Connection struct {
|
||||||
conn net.Conn
|
conn net.Conn
|
||||||
|
|
||||||
// waiting until reply finished
|
// waiting until protocol finished
|
||||||
waitingReply wait.Wait
|
waitingReply wait.Wait
|
||||||
|
|
||||||
// lock while server sending response
|
// lock while server sending response
|
||||||
|
@@ -6,7 +6,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"github.com/hdt3213/godis/interface/redis"
|
"github.com/hdt3213/godis/interface/redis"
|
||||||
"github.com/hdt3213/godis/lib/logger"
|
"github.com/hdt3213/godis/lib/logger"
|
||||||
"github.com/hdt3213/godis/redis/reply"
|
"github.com/hdt3213/godis/redis/protocol"
|
||||||
"io"
|
"io"
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
"strconv"
|
"strconv"
|
||||||
@@ -34,7 +34,7 @@ func ParseBytes(data []byte) ([]redis.Reply, error) {
|
|||||||
var results []redis.Reply
|
var results []redis.Reply
|
||||||
for payload := range ch {
|
for payload := range ch {
|
||||||
if payload == nil {
|
if payload == nil {
|
||||||
return nil, errors.New("no reply")
|
return nil, errors.New("no protocol")
|
||||||
}
|
}
|
||||||
if payload.Err != nil {
|
if payload.Err != nil {
|
||||||
if payload.Err == io.EOF {
|
if payload.Err == io.EOF {
|
||||||
@@ -54,7 +54,7 @@ func ParseOne(data []byte) (redis.Reply, error) {
|
|||||||
go parse0(reader, ch)
|
go parse0(reader, ch)
|
||||||
payload := <-ch // parse0 will close the channel
|
payload := <-ch // parse0 will close the channel
|
||||||
if payload == nil {
|
if payload == nil {
|
||||||
return nil, errors.New("no reply")
|
return nil, errors.New("no protocol")
|
||||||
}
|
}
|
||||||
return payload.Data, payload.Err
|
return payload.Data, payload.Err
|
||||||
}
|
}
|
||||||
@@ -105,7 +105,7 @@ func parse0(reader io.Reader, ch chan<- *Payload) {
|
|||||||
if !state.readingMultiLine {
|
if !state.readingMultiLine {
|
||||||
// receive new response
|
// receive new response
|
||||||
if msg[0] == '*' {
|
if msg[0] == '*' {
|
||||||
// multi bulk reply
|
// multi bulk protocol
|
||||||
err = parseMultiBulkHeader(msg, &state)
|
err = parseMultiBulkHeader(msg, &state)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ch <- &Payload{
|
ch <- &Payload{
|
||||||
@@ -116,12 +116,12 @@ func parse0(reader io.Reader, ch chan<- *Payload) {
|
|||||||
}
|
}
|
||||||
if state.expectedArgsCount == 0 {
|
if state.expectedArgsCount == 0 {
|
||||||
ch <- &Payload{
|
ch <- &Payload{
|
||||||
Data: &reply.EmptyMultiBulkReply{},
|
Data: &protocol.EmptyMultiBulkReply{},
|
||||||
}
|
}
|
||||||
state = readState{} // reset state
|
state = readState{} // reset state
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
} else if msg[0] == '$' { // bulk reply
|
} else if msg[0] == '$' { // bulk protocol
|
||||||
err = parseBulkHeader(msg, &state)
|
err = parseBulkHeader(msg, &state)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ch <- &Payload{
|
ch <- &Payload{
|
||||||
@@ -130,15 +130,15 @@ func parse0(reader io.Reader, ch chan<- *Payload) {
|
|||||||
state = readState{} // reset state
|
state = readState{} // reset state
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if state.bulkLen == -1 { // null bulk reply
|
if state.bulkLen == -1 { // null bulk protocol
|
||||||
ch <- &Payload{
|
ch <- &Payload{
|
||||||
Data: &reply.NullBulkReply{},
|
Data: &protocol.NullBulkReply{},
|
||||||
}
|
}
|
||||||
state = readState{} // reset state
|
state = readState{} // reset state
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// single line reply
|
// single line protocol
|
||||||
result, err := parseSingleLineReply(msg)
|
result, err := parseSingleLineReply(msg)
|
||||||
ch <- &Payload{
|
ch <- &Payload{
|
||||||
Data: result,
|
Data: result,
|
||||||
@@ -148,7 +148,7 @@ func parse0(reader io.Reader, ch chan<- *Payload) {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// receive following bulk reply
|
// receive following bulk protocol
|
||||||
err = readBody(msg, &state)
|
err = readBody(msg, &state)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ch <- &Payload{
|
ch <- &Payload{
|
||||||
@@ -161,9 +161,9 @@ func parse0(reader io.Reader, ch chan<- *Payload) {
|
|||||||
if state.finished() {
|
if state.finished() {
|
||||||
var result redis.Reply
|
var result redis.Reply
|
||||||
if state.msgType == '*' {
|
if state.msgType == '*' {
|
||||||
result = reply.MakeMultiBulkReply(state.args)
|
result = protocol.MakeMultiBulkReply(state.args)
|
||||||
} else if state.msgType == '$' {
|
} else if state.msgType == '$' {
|
||||||
result = reply.MakeBulkReply(state.args[0])
|
result = protocol.MakeBulkReply(state.args[0])
|
||||||
}
|
}
|
||||||
ch <- &Payload{
|
ch <- &Payload{
|
||||||
Data: result,
|
Data: result,
|
||||||
@@ -213,7 +213,7 @@ func parseMultiBulkHeader(msg []byte, state *readState) error {
|
|||||||
state.expectedArgsCount = 0
|
state.expectedArgsCount = 0
|
||||||
return nil
|
return nil
|
||||||
} else if expectedLine > 0 {
|
} else if expectedLine > 0 {
|
||||||
// first line of multi bulk reply
|
// first line of multi bulk protocol
|
||||||
state.msgType = msg[0]
|
state.msgType = msg[0]
|
||||||
state.readingMultiLine = true
|
state.readingMultiLine = true
|
||||||
state.expectedArgsCount = int(expectedLine)
|
state.expectedArgsCount = int(expectedLine)
|
||||||
@@ -247,16 +247,16 @@ func parseSingleLineReply(msg []byte) (redis.Reply, error) {
|
|||||||
str := strings.TrimSuffix(string(msg), "\r\n")
|
str := strings.TrimSuffix(string(msg), "\r\n")
|
||||||
var result redis.Reply
|
var result redis.Reply
|
||||||
switch msg[0] {
|
switch msg[0] {
|
||||||
case '+': // status reply
|
case '+': // status protocol
|
||||||
result = reply.MakeStatusReply(str[1:])
|
result = protocol.MakeStatusReply(str[1:])
|
||||||
case '-': // err reply
|
case '-': // err protocol
|
||||||
result = reply.MakeErrReply(str[1:])
|
result = protocol.MakeErrReply(str[1:])
|
||||||
case ':': // int reply
|
case ':': // int protocol
|
||||||
val, err := strconv.ParseInt(str[1:], 10, 64)
|
val, err := strconv.ParseInt(str[1:], 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, errors.New("protocol error: " + string(msg))
|
return nil, errors.New("protocol error: " + string(msg))
|
||||||
}
|
}
|
||||||
result = reply.MakeIntReply(val)
|
result = protocol.MakeIntReply(val)
|
||||||
default:
|
default:
|
||||||
// parse as text protocol
|
// parse as text protocol
|
||||||
strs := strings.Split(str, " ")
|
strs := strings.Split(str, " ")
|
||||||
@@ -264,17 +264,17 @@ func parseSingleLineReply(msg []byte) (redis.Reply, error) {
|
|||||||
for i, s := range strs {
|
for i, s := range strs {
|
||||||
args[i] = []byte(s)
|
args[i] = []byte(s)
|
||||||
}
|
}
|
||||||
result = reply.MakeMultiBulkReply(args)
|
result = protocol.MakeMultiBulkReply(args)
|
||||||
}
|
}
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// read the non-first lines of multi bulk reply or bulk reply
|
// read the non-first lines of multi bulk protocol or bulk protocol
|
||||||
func readBody(msg []byte, state *readState) error {
|
func readBody(msg []byte, state *readState) error {
|
||||||
line := msg[0 : len(msg)-2]
|
line := msg[0 : len(msg)-2]
|
||||||
var err error
|
var err error
|
||||||
if line[0] == '$' {
|
if line[0] == '$' {
|
||||||
// bulk reply
|
// bulk protocol
|
||||||
state.bulkLen, err = strconv.ParseInt(string(line[1:]), 10, 64)
|
state.bulkLen, err = strconv.ParseInt(string(line[1:]), 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.New("protocol error: " + string(msg))
|
return errors.New("protocol error: " + string(msg))
|
||||||
|
@@ -4,32 +4,32 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"github.com/hdt3213/godis/interface/redis"
|
"github.com/hdt3213/godis/interface/redis"
|
||||||
"github.com/hdt3213/godis/lib/utils"
|
"github.com/hdt3213/godis/lib/utils"
|
||||||
"github.com/hdt3213/godis/redis/reply"
|
"github.com/hdt3213/godis/redis/protocol"
|
||||||
"io"
|
"io"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestParseStream(t *testing.T) {
|
func TestParseStream(t *testing.T) {
|
||||||
replies := []redis.Reply{
|
replies := []redis.Reply{
|
||||||
reply.MakeIntReply(1),
|
protocol.MakeIntReply(1),
|
||||||
reply.MakeStatusReply("OK"),
|
protocol.MakeStatusReply("OK"),
|
||||||
reply.MakeErrReply("ERR unknown"),
|
protocol.MakeErrReply("ERR unknown"),
|
||||||
reply.MakeBulkReply([]byte("a\r\nb")), // test binary safe
|
protocol.MakeBulkReply([]byte("a\r\nb")), // test binary safe
|
||||||
reply.MakeNullBulkReply(),
|
protocol.MakeNullBulkReply(),
|
||||||
reply.MakeMultiBulkReply([][]byte{
|
protocol.MakeMultiBulkReply([][]byte{
|
||||||
[]byte("a"),
|
[]byte("a"),
|
||||||
[]byte("\r\n"),
|
[]byte("\r\n"),
|
||||||
}),
|
}),
|
||||||
reply.MakeEmptyMultiBulkReply(),
|
protocol.MakeEmptyMultiBulkReply(),
|
||||||
}
|
}
|
||||||
reqs := bytes.Buffer{}
|
reqs := bytes.Buffer{}
|
||||||
for _, re := range replies {
|
for _, re := range replies {
|
||||||
reqs.Write(re.ToBytes())
|
reqs.Write(re.ToBytes())
|
||||||
}
|
}
|
||||||
reqs.Write([]byte("set a a" + reply.CRLF)) // test text protocol
|
reqs.Write([]byte("set a a" + protocol.CRLF)) // test text protocol
|
||||||
expected := make([]redis.Reply, len(replies))
|
expected := make([]redis.Reply, len(replies))
|
||||||
copy(expected, replies)
|
copy(expected, replies)
|
||||||
expected = append(expected, reply.MakeMultiBulkReply([][]byte{
|
expected = append(expected, protocol.MakeMultiBulkReply([][]byte{
|
||||||
[]byte("set"), []byte("a"), []byte("a"),
|
[]byte("set"), []byte("a"), []byte("a"),
|
||||||
}))
|
}))
|
||||||
|
|
||||||
@@ -57,16 +57,16 @@ func TestParseStream(t *testing.T) {
|
|||||||
|
|
||||||
func TestParseOne(t *testing.T) {
|
func TestParseOne(t *testing.T) {
|
||||||
replies := []redis.Reply{
|
replies := []redis.Reply{
|
||||||
reply.MakeIntReply(1),
|
protocol.MakeIntReply(1),
|
||||||
reply.MakeStatusReply("OK"),
|
protocol.MakeStatusReply("OK"),
|
||||||
reply.MakeErrReply("ERR unknown"),
|
protocol.MakeErrReply("ERR unknown"),
|
||||||
reply.MakeBulkReply([]byte("a\r\nb")), // test binary safe
|
protocol.MakeBulkReply([]byte("a\r\nb")), // test binary safe
|
||||||
reply.MakeNullBulkReply(),
|
protocol.MakeNullBulkReply(),
|
||||||
reply.MakeMultiBulkReply([][]byte{
|
protocol.MakeMultiBulkReply([][]byte{
|
||||||
[]byte("a"),
|
[]byte("a"),
|
||||||
[]byte("\r\n"),
|
[]byte("\r\n"),
|
||||||
}),
|
}),
|
||||||
reply.MakeEmptyMultiBulkReply(),
|
protocol.MakeEmptyMultiBulkReply(),
|
||||||
}
|
}
|
||||||
for _, re := range replies {
|
for _, re := range replies {
|
||||||
result, err := ParseOne(re.ToBytes())
|
result, err := ParseOne(re.ToBytes())
|
||||||
|
@@ -4,16 +4,16 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"github.com/hdt3213/godis/interface/redis"
|
"github.com/hdt3213/godis/interface/redis"
|
||||||
"github.com/hdt3213/godis/lib/utils"
|
"github.com/hdt3213/godis/lib/utils"
|
||||||
"github.com/hdt3213/godis/redis/reply"
|
"github.com/hdt3213/godis/redis/protocol"
|
||||||
"runtime"
|
"runtime"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AssertIntReply checks if the given redis.Reply is the expected integer
|
// AssertIntReply checks if the given redis.Reply is the expected integer
|
||||||
func AssertIntReply(t *testing.T, actual redis.Reply, expected int) {
|
func AssertIntReply(t *testing.T, actual redis.Reply, expected int) {
|
||||||
intResult, ok := actual.(*reply.IntReply)
|
intResult, ok := actual.(*protocol.IntReply)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Errorf("expected int reply, actually %s, %s", actual.ToBytes(), printStack())
|
t.Errorf("expected int protocol, actually %s, %s", actual.ToBytes(), printStack())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if intResult.Code != int64(expected) {
|
if intResult.Code != int64(expected) {
|
||||||
@@ -23,9 +23,9 @@ func AssertIntReply(t *testing.T, actual redis.Reply, expected int) {
|
|||||||
|
|
||||||
// AssertBulkReply checks if the given redis.Reply is the expected string
|
// AssertBulkReply checks if the given redis.Reply is the expected string
|
||||||
func AssertBulkReply(t *testing.T, actual redis.Reply, expected string) {
|
func AssertBulkReply(t *testing.T, actual redis.Reply, expected string) {
|
||||||
bulkReply, ok := actual.(*reply.BulkReply)
|
bulkReply, ok := actual.(*protocol.BulkReply)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Errorf("expected bulk reply, actually %s, %s", actual.ToBytes(), printStack())
|
t.Errorf("expected bulk protocol, actually %s, %s", actual.ToBytes(), printStack())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !utils.BytesEquals(bulkReply.Arg, []byte(expected)) {
|
if !utils.BytesEquals(bulkReply.Arg, []byte(expected)) {
|
||||||
@@ -35,14 +35,14 @@ func AssertBulkReply(t *testing.T, actual redis.Reply, expected string) {
|
|||||||
|
|
||||||
// AssertStatusReply checks if the given redis.Reply is the expected status
|
// AssertStatusReply checks if the given redis.Reply is the expected status
|
||||||
func AssertStatusReply(t *testing.T, actual redis.Reply, expected string) {
|
func AssertStatusReply(t *testing.T, actual redis.Reply, expected string) {
|
||||||
statusReply, ok := actual.(*reply.StatusReply)
|
statusReply, ok := actual.(*protocol.StatusReply)
|
||||||
if !ok {
|
if !ok {
|
||||||
// may be a reply.OkReply e.g.
|
// may be a protocol.OkReply e.g.
|
||||||
expectBytes := reply.MakeStatusReply(expected).ToBytes()
|
expectBytes := protocol.MakeStatusReply(expected).ToBytes()
|
||||||
if utils.BytesEquals(actual.ToBytes(), expectBytes) {
|
if utils.BytesEquals(actual.ToBytes(), expectBytes) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
t.Errorf("expected bulk reply, actually %s, %s", actual.ToBytes(), printStack())
|
t.Errorf("expected bulk protocol, actually %s, %s", actual.ToBytes(), printStack())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if statusReply.Status != expected {
|
if statusReply.Status != expected {
|
||||||
@@ -52,13 +52,13 @@ func AssertStatusReply(t *testing.T, actual redis.Reply, expected string) {
|
|||||||
|
|
||||||
// AssertErrReply checks if the given redis.Reply is the expected error
|
// AssertErrReply checks if the given redis.Reply is the expected error
|
||||||
func AssertErrReply(t *testing.T, actual redis.Reply, expected string) {
|
func AssertErrReply(t *testing.T, actual redis.Reply, expected string) {
|
||||||
errReply, ok := actual.(reply.ErrorReply)
|
errReply, ok := actual.(protocol.ErrorReply)
|
||||||
if !ok {
|
if !ok {
|
||||||
expectBytes := reply.MakeErrReply(expected).ToBytes()
|
expectBytes := protocol.MakeErrReply(expected).ToBytes()
|
||||||
if utils.BytesEquals(actual.ToBytes(), expectBytes) {
|
if utils.BytesEquals(actual.ToBytes(), expectBytes) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
t.Errorf("expected err reply, actually %s, %s", actual.ToBytes(), printStack())
|
t.Errorf("expected err protocol, actually %s, %s", actual.ToBytes(), printStack())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if errReply.Error() != expected {
|
if errReply.Error() != expected {
|
||||||
@@ -66,7 +66,7 @@ func AssertErrReply(t *testing.T, actual redis.Reply, expected string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// AssertNotError checks if the given redis.Reply is not error reply
|
// AssertNotError checks if the given redis.Reply is not error protocol
|
||||||
func AssertNotError(t *testing.T, result redis.Reply) {
|
func AssertNotError(t *testing.T, result redis.Reply) {
|
||||||
if result == nil {
|
if result == nil {
|
||||||
t.Errorf("result is nil %s", printStack())
|
t.Errorf("result is nil %s", printStack())
|
||||||
@@ -78,11 +78,11 @@ func AssertNotError(t *testing.T, result redis.Reply) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if bytes[0] == '-' {
|
if bytes[0] == '-' {
|
||||||
t.Errorf("result is err reply %s", printStack())
|
t.Errorf("result is err protocol %s", printStack())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// AssertNullBulk checks if the given redis.Reply is reply.NullBulkReply
|
// AssertNullBulk checks if the given redis.Reply is protocol.NullBulkReply
|
||||||
func AssertNullBulk(t *testing.T, result redis.Reply) {
|
func AssertNullBulk(t *testing.T, result redis.Reply) {
|
||||||
if result == nil {
|
if result == nil {
|
||||||
t.Errorf("result is nil %s", printStack())
|
t.Errorf("result is nil %s", printStack())
|
||||||
@@ -93,17 +93,17 @@ func AssertNullBulk(t *testing.T, result redis.Reply) {
|
|||||||
t.Errorf("result is empty %s", printStack())
|
t.Errorf("result is empty %s", printStack())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
expect := (&reply.NullBulkReply{}).ToBytes()
|
expect := (&protocol.NullBulkReply{}).ToBytes()
|
||||||
if !utils.BytesEquals(expect, bytes) {
|
if !utils.BytesEquals(expect, bytes) {
|
||||||
t.Errorf("result is not null-bulk-reply %s", printStack())
|
t.Errorf("result is not null-bulk-protocol %s", printStack())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// AssertMultiBulkReply checks if the given redis.Reply has the expected content
|
// AssertMultiBulkReply checks if the given redis.Reply has the expected content
|
||||||
func AssertMultiBulkReply(t *testing.T, actual redis.Reply, expected []string) {
|
func AssertMultiBulkReply(t *testing.T, actual redis.Reply, expected []string) {
|
||||||
multiBulk, ok := actual.(*reply.MultiBulkReply)
|
multiBulk, ok := actual.(*protocol.MultiBulkReply)
|
||||||
if !ok {
|
if !ok {
|
||||||
t.Errorf("expected bulk reply, actually %s, %s", actual.ToBytes(), printStack())
|
t.Errorf("expected bulk protocol, actually %s, %s", actual.ToBytes(), printStack())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if len(multiBulk.Args) != len(expected) {
|
if len(multiBulk.Args) != len(expected) {
|
||||||
@@ -121,13 +121,13 @@ func AssertMultiBulkReply(t *testing.T, actual redis.Reply, expected []string) {
|
|||||||
|
|
||||||
// AssertMultiBulkReplySize check if redis.Reply has expected length
|
// AssertMultiBulkReplySize check if redis.Reply has expected length
|
||||||
func AssertMultiBulkReplySize(t *testing.T, actual redis.Reply, expected int) {
|
func AssertMultiBulkReplySize(t *testing.T, actual redis.Reply, expected int) {
|
||||||
multiBulk, ok := actual.(*reply.MultiBulkReply)
|
multiBulk, ok := actual.(*protocol.MultiBulkReply)
|
||||||
if !ok {
|
if !ok {
|
||||||
if expected == 0 &&
|
if expected == 0 &&
|
||||||
utils.BytesEquals(actual.ToBytes(), reply.MakeEmptyMultiBulkReply().ToBytes()) {
|
utils.BytesEquals(actual.ToBytes(), protocol.MakeEmptyMultiBulkReply().ToBytes()) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
t.Errorf("expected bulk reply, actually %s, %s", actual.ToBytes(), printStack())
|
t.Errorf("expected bulk protocol, actually %s, %s", actual.ToBytes(), printStack())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if len(multiBulk.Args) != expected {
|
if len(multiBulk.Args) != expected {
|
@@ -1,4 +1,4 @@
|
|||||||
package reply
|
package protocol
|
||||||
|
|
||||||
// PongReply is +PONG
|
// PongReply is +PONG
|
||||||
type PongReply struct{}
|
type PongReply struct{}
|
||||||
@@ -22,7 +22,7 @@ func (r *OkReply) ToBytes() []byte {
|
|||||||
|
|
||||||
var theOkReply = new(OkReply)
|
var theOkReply = new(OkReply)
|
||||||
|
|
||||||
// MakeOkReply returns a ok reply
|
// MakeOkReply returns a ok protocol
|
||||||
func MakeOkReply() *OkReply {
|
func MakeOkReply() *OkReply {
|
||||||
return theOkReply
|
return theOkReply
|
||||||
}
|
}
|
||||||
@@ -79,7 +79,7 @@ func (r *QueuedReply) ToBytes() []byte {
|
|||||||
|
|
||||||
var theQueuedReply = new(QueuedReply)
|
var theQueuedReply = new(QueuedReply)
|
||||||
|
|
||||||
// MakeQueuedReply returns a QUEUED reply
|
// MakeQueuedReply returns a QUEUED protocol
|
||||||
func MakeQueuedReply() *QueuedReply {
|
func MakeQueuedReply() *QueuedReply {
|
||||||
return theQueuedReply
|
return theQueuedReply
|
||||||
}
|
}
|
@@ -1,4 +1,4 @@
|
|||||||
package reply
|
package protocol
|
||||||
|
|
||||||
// UnknownErrReply represents UnknownErr
|
// UnknownErrReply represents UnknownErr
|
||||||
type UnknownErrReply struct{}
|
type UnknownErrReply struct{}
|
@@ -1,4 +1,4 @@
|
|||||||
package reply
|
package protocol
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
@@ -115,7 +115,7 @@ type IntReply struct {
|
|||||||
Code int64
|
Code int64
|
||||||
}
|
}
|
||||||
|
|
||||||
// MakeIntReply creates int reply
|
// MakeIntReply creates int protocol
|
||||||
func MakeIntReply(code int64) *IntReply {
|
func MakeIntReply(code int64) *IntReply {
|
||||||
return &IntReply{
|
return &IntReply{
|
||||||
Code: code,
|
Code: code,
|
||||||
@@ -147,7 +147,7 @@ func MakeErrReply(status string) *StandardErrReply {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// IsErrorReply returns true if the given reply is error
|
// IsErrorReply returns true if the given protocol is error
|
||||||
func IsErrorReply(reply redis.Reply) bool {
|
func IsErrorReply(reply redis.Reply) bool {
|
||||||
return reply.ToBytes()[0] == '-'
|
return reply.ToBytes()[0] == '-'
|
||||||
}
|
}
|
@@ -5,7 +5,7 @@ import (
|
|||||||
"github.com/hdt3213/godis/pubsub"
|
"github.com/hdt3213/godis/pubsub"
|
||||||
"github.com/hdt3213/godis/redis/connection"
|
"github.com/hdt3213/godis/redis/connection"
|
||||||
"github.com/hdt3213/godis/redis/parser"
|
"github.com/hdt3213/godis/redis/parser"
|
||||||
"github.com/hdt3213/godis/redis/reply/asserts"
|
"github.com/hdt3213/godis/redis/protocol/asserts"
|
||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@@ -14,7 +14,7 @@ import (
|
|||||||
"github.com/hdt3213/godis/lib/sync/atomic"
|
"github.com/hdt3213/godis/lib/sync/atomic"
|
||||||
"github.com/hdt3213/godis/redis/connection"
|
"github.com/hdt3213/godis/redis/connection"
|
||||||
"github.com/hdt3213/godis/redis/parser"
|
"github.com/hdt3213/godis/redis/parser"
|
||||||
"github.com/hdt3213/godis/redis/reply"
|
"github.com/hdt3213/godis/redis/protocol"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"strings"
|
"strings"
|
||||||
@@ -75,7 +75,7 @@ func (h *Handler) Handle(ctx context.Context, conn net.Conn) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
// protocol err
|
// protocol err
|
||||||
errReply := reply.MakeErrReply(payload.Err.Error())
|
errReply := protocol.MakeErrReply(payload.Err.Error())
|
||||||
err := client.Write(errReply.ToBytes())
|
err := client.Write(errReply.ToBytes())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
h.closeClient(client)
|
h.closeClient(client)
|
||||||
@@ -88,9 +88,9 @@ func (h *Handler) Handle(ctx context.Context, conn net.Conn) {
|
|||||||
logger.Error("empty payload")
|
logger.Error("empty payload")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
r, ok := payload.Data.(*reply.MultiBulkReply)
|
r, ok := payload.Data.(*protocol.MultiBulkReply)
|
||||||
if !ok {
|
if !ok {
|
||||||
logger.Error("require multi bulk reply")
|
logger.Error("require multi bulk protocol")
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
result := h.db.Exec(client, r.Args)
|
result := h.db.Exec(client, r.Args)
|
||||||
|
Reference in New Issue
Block a user