refactor command command

This commit is contained in:
hdt3213
2023-05-04 23:03:06 +08:00
committed by finley
parent 1e767b6797
commit 68d7f28b1a
15 changed files with 434 additions and 422 deletions

View File

@@ -129,11 +129,11 @@ func execCopyTo(db *DB, args [][]byte) redis.Reply {
} }
func init() { func init() {
RegisterCommand("DumpKey", execDumpKey, writeAllKeys, undoDel, 2, flagReadOnly) registerCommand("DumpKey", execDumpKey, writeAllKeys, undoDel, 2, flagReadOnly)
RegisterCommand("ExistIn", execExistIn, readAllKeys, nil, -1, flagReadOnly) registerCommand("ExistIn", execExistIn, readAllKeys, nil, -1, flagReadOnly)
RegisterCommand("RenameFrom", execRenameFrom, readFirstKey, nil, 2, flagWrite) registerCommand("RenameFrom", execRenameFrom, readFirstKey, nil, 2, flagWrite)
RegisterCommand("RenameTo", execRenameTo, writeFirstKey, rollbackFirstKey, 4, flagWrite) registerCommand("RenameTo", execRenameTo, writeFirstKey, rollbackFirstKey, 4, flagWrite)
RegisterCommand("RenameNxTo", execRenameTo, writeFirstKey, rollbackFirstKey, 4, flagWrite) registerCommand("RenameNxTo", execRenameTo, writeFirstKey, rollbackFirstKey, 4, flagWrite)
RegisterCommand("CopyFrom", execCopyFrom, readFirstKey, nil, 2, flagReadOnly) registerCommand("CopyFrom", execCopyFrom, readFirstKey, nil, 2, flagReadOnly)
RegisterCommand("CopyTo", execCopyTo, writeFirstKey, rollbackFirstKey, 5, flagWrite) registerCommand("CopyTo", execCopyTo, writeFirstKey, rollbackFirstKey, 5, flagWrite)
} }

View File

@@ -1,171 +0,0 @@
package database
import (
"github.com/hdt3213/godis/interface/redis"
"github.com/hdt3213/godis/redis/protocol"
"strings"
)
func init() {
}
var commandTable = make(map[string]*godisCommand)
const (
Write = "write"
Readonly = "readonly"
Denyoom = "denyoom"
Admin = "admin"
Pubsub = "pubsub"
Noscript = "noscript"
Random = "random"
SortForScript = "sortforscript"
Loading = "loading"
Stale = "stale"
SkipMonitor = "skip_monitor"
Asking = "asking"
Fast = "fast"
Movablekeys = "movablekeys"
)
type godisCommand struct {
name string
arity int
signs []string
firstKey int
lastKey int
stepNumber int
prepare PreFunc
}
func RegisterGodisCommand(name string, arity int, signs []string, firstKey int, lastKey int, stepNumber int, prepare PreFunc) {
name = strings.ToLower(name)
commandTable[name] = &godisCommand{
name: name,
arity: arity,
signs: signs,
firstKey: firstKey,
lastKey: lastKey,
stepNumber: stepNumber,
prepare: prepare,
}
}
func execCommand(args [][]byte) redis.Reply {
n := len(args)
if n > 1 {
subCommand := strings.ToUpper(string(args[1]))
if subCommand == "INFO" {
return getCommands(args[2:])
} else if subCommand == "COUNT" {
return protocol.MakeIntReply(int64(len(commandTable)))
} else if subCommand == "GETKEYS" {
if n < 2 {
return protocol.MakeErrReply("Unknown subcommand or wrong number of arguments for '" + subCommand + "'")
}
return getKeys(args[2:])
} else {
return protocol.MakeErrReply("Unknow subcomand or wrong number of arguments for '" + subCommand + "'")
}
} else {
return getAllGodisCommandReply()
}
}
func getKeys(args [][]byte) redis.Reply {
key := string(args[0])
command, ok := commandTable[key]
if !ok {
return protocol.MakeErrReply("Invalid command specified")
}
arity := command.arity
if arity > 0 {
if len(args) != arity {
return protocol.MakeErrReply("Invalid number of arguments specified for command")
}
} else {
if len(args) < -arity {
return protocol.MakeErrReply("Invalid number of arguments specified for command")
}
}
prepare := command.prepare
if prepare == nil {
return protocol.MakeErrReply("The command has no key arguments")
}
writeKeys, readKeys := prepare(args[1:])
keys := append(writeKeys, readKeys...)
replies := make([]redis.Reply, len(keys))
for i, key := range keys {
replies[i] = protocol.MakeBulkReply([]byte(key))
}
return protocol.MakeMultiRawReply(replies)
}
func getCommands(args [][]byte) redis.Reply {
replies := make([]redis.Reply, len(args))
for i, v := range args {
reply, ok := commandTable[string(v)]
if ok {
replies[i] = reply.ToReply()
} else {
replies[i] = protocol.MakeNullBulkReply()
}
}
return protocol.MakeMultiRawReply(replies)
}
func getAllGodisCommandReply() redis.Reply {
replies := make([]redis.Reply, len(commandTable))
i := 0
for _, v := range commandTable {
replies[i] = v.ToReply()
i++
}
return protocol.MakeMultiRawReply(replies)
}
func (g *godisCommand) ToReply() redis.Reply {
args := make([]redis.Reply, 6)
args[0] = protocol.MakeBulkReply([]byte(g.name))
args[1] = protocol.MakeIntReply(int64(g.arity))
signs := make([]redis.Reply, len(g.signs))
for i, v := range g.signs {
signs[i] = protocol.MakeStatusReply(v)
}
args[2] = protocol.MakeMultiRawReply(signs)
args[3] = protocol.MakeIntReply(int64(g.firstKey))
args[4] = protocol.MakeIntReply(int64(g.lastKey))
args[5] = protocol.MakeIntReply(int64(g.stepNumber))
return protocol.MakeMultiRawReply(args)
}
func init() {
RegisterGodisCommand("Command", 0, []string{Random, Loading, Stale}, 0, 0, 0, nil)
RegisterGodisCommand("Keys", 2, []string{Readonly, SortForScript}, 0, 0, 0, nil)
RegisterGodisCommand("Auth", 2, []string{Noscript, Loading, Stale, SkipMonitor, Fast}, 0, 0, 0, nil)
RegisterGodisCommand("Info", -1, []string{Random, Loading, Stale}, 0, 0, 0, nil)
RegisterGodisCommand("Slaveof", 3, []string{Admin, Noscript, Stale}, 0, 0, 0, nil)
RegisterGodisCommand("Subscribe", -2, []string{Pubsub, Noscript, Loading, Stale}, 0, 0, 0, nil)
RegisterGodisCommand("Publish", 3, []string{Pubsub, Noscript, Loading, Fast}, 0, 0, 0, nil)
RegisterGodisCommand("FlushAll", -1, []string{Write}, 0, 0, 0, nil)
RegisterGodisCommand("FlushDb", -1, []string{Write}, 0, 0, 0, nil)
RegisterGodisCommand("Save", 1, []string{Admin, Noscript}, 0, 0, 0, nil)
RegisterGodisCommand("BgSave", 1, []string{Admin, Noscript}, 0, 0, 0, nil)
RegisterGodisCommand("Select", 2, []string{Loading, Fast}, 0, 0, 0, nil)
RegisterGodisCommand("Replconf", -1, []string{Admin, Noscript, Loading, Stale}, 0, 0, 0, nil)
RegisterGodisCommand("Replconf", 3, []string{Readonly, Admin, Noscript}, 0, 0, 0, nil)
// transaction command
RegisterGodisCommand("Multi", 1, []string{Noscript, Fast}, 0, 0, 0, nil)
RegisterGodisCommand("Discard", 1, []string{Noscript, Fast}, 0, 0, 0, nil)
RegisterGodisCommand("Exec", 1, []string{Noscript, SkipMonitor}, 0, 0, 0, nil)
RegisterGodisCommand("Watch", 1, []string{Noscript, Fast}, 1, -1, 1, readAllKeys)
}

128
database/commandinfo.go Normal file
View File

@@ -0,0 +1,128 @@
package database
import (
"github.com/hdt3213/godis/interface/redis"
"github.com/hdt3213/godis/redis/protocol"
"strings"
)
const (
redisFlagWrite = "write"
redisFlagReadonly = "readonly"
redisFlagDenyOOM = "denyoom"
redisFlagAdmin = "admin"
redisFlagPubSub = "pubsub"
redisFlagNoScript = "noscript"
redisFlagRandom = "random"
redisFlagSortForScript = "sortforscript"
redisFlagLoading = "loading"
redisFlagStale = "stale"
redisFlagSkipMonitor = "skip_monitor"
redisFlagAsking = "asking"
redisFlagFast = "fast"
redisFlagMovableKeys = "movablekeys"
)
func execCommand(args [][]byte) redis.Reply {
n := len(args)
if n > 1 {
subCommand := strings.ToLower(string(args[1]))
if subCommand == "info" {
return getCommands(args[2:])
} else if subCommand == "count" {
return protocol.MakeIntReply(int64(len(cmdTable)))
} else if subCommand == "getkeys" {
if n < 2 {
return protocol.MakeErrReply("Unknown subcommand or wrong number of arguments for '" + subCommand + "'")
}
return getKeys(args[2:])
} else {
return protocol.MakeErrReply("Unknown subcommand or wrong number of arguments for '" + subCommand + "'")
}
} else {
return getAllGodisCommandReply()
}
}
func getKeys(args [][]byte) redis.Reply {
cmdName := string(args[0])
cmd, ok := cmdTable[cmdName]
if !ok {
return protocol.MakeErrReply("Invalid command specified")
}
if !validateArity(cmd.arity, args[1:]) {
return protocol.MakeArgNumErrReply(cmdName)
}
if cmd.prepare == nil {
return protocol.MakeErrReply("The command has no key arguments")
}
writeKeys, readKeys := cmd.prepare(args[1:])
keys := append(writeKeys, readKeys...)
resp := make([][]byte, len(keys))
for i, key := range keys {
resp[i] = []byte(key)
}
return protocol.MakeMultiBulkReply(resp)
}
func getCommands(args [][]byte) redis.Reply {
replies := make([]redis.Reply, len(args))
for i, v := range args {
cmd, ok := cmdTable[string(v)]
if ok {
replies[i] = cmd.toDescReply()
} else {
replies[i] = protocol.MakeNullBulkReply()
}
}
return protocol.MakeMultiRawReply(replies)
}
func getAllGodisCommandReply() redis.Reply {
replies := make([]redis.Reply, 0, len(cmdTable))
for _, v := range cmdTable {
replies = append(replies, v.toDescReply())
}
return protocol.MakeMultiRawReply(replies)
}
func init() {
registerSpecialCommand("Command", 0, 0).
attachCommandExtra([]string{redisFlagRandom, redisFlagLoading, redisFlagStale}, 0, 0, 0)
registerSpecialCommand("Keys", 2, 0).
attachCommandExtra([]string{redisFlagReadonly, redisFlagSortForScript}, 0, 0, 0)
registerSpecialCommand("Auth", 2, 0).
attachCommandExtra([]string{redisFlagNoScript, redisFlagLoading, redisFlagStale, redisFlagSkipMonitor, redisFlagFast}, 0, 0, 0)
registerSpecialCommand("Info", -1, 0).
attachCommandExtra([]string{redisFlagRandom, redisFlagLoading, redisFlagStale}, 0, 0, 0)
registerSpecialCommand("SlaveOf", 3, 0).
attachCommandExtra([]string{redisFlagAdmin, redisFlagNoScript, redisFlagStale}, 0, 0, 0)
registerSpecialCommand("Subscribe", -2, 0).
attachCommandExtra([]string{redisFlagPubSub, redisFlagNoScript, redisFlagLoading, redisFlagStale}, 0, 0, 0)
registerSpecialCommand("Publish", 3, 0).
attachCommandExtra([]string{redisFlagPubSub, redisFlagNoScript, redisFlagLoading, redisFlagFast}, 0, 0, 0)
registerSpecialCommand("FlushAll", -1, 0).
attachCommandExtra([]string{redisFlagWrite}, 0, 0, 0)
registerSpecialCommand("FlushDB", -1, 0).
attachCommandExtra([]string{redisFlagWrite}, 0, 0, 0)
registerSpecialCommand("Save", -1, 0).
attachCommandExtra([]string{redisFlagAdmin, redisFlagNoScript}, 0, 0, 0)
registerSpecialCommand("BgSave", 1, 0).
attachCommandExtra([]string{redisFlagAdmin, redisFlagNoScript}, 0, 0, 0)
registerSpecialCommand("Select", 2, 0).
attachCommandExtra([]string{redisFlagLoading, redisFlagFast}, 0, 0, 0)
registerSpecialCommand("ReplConf", -1, 0).
attachCommandExtra([]string{redisFlagAdmin, redisFlagNoScript, redisFlagLoading, redisFlagStale}, 0, 0, 0)
//attachCommandExtra("ReplConf", 3, []string{redisFlagReadonly, redisFlagAdmin, redisFlagNoScript}, 0, 0, 0, nil)
// transaction command
registerSpecialCommand("Multi", 1, 0).
attachCommandExtra([]string{redisFlagNoScript, redisFlagFast}, 0, 0, 0)
registerSpecialCommand("Discard", 1, 0).
attachCommandExtra([]string{redisFlagNoScript, redisFlagFast}, 0, 0, 0)
registerSpecialCommand("Exec", 1, 0).
attachCommandExtra([]string{redisFlagNoScript, redisFlagSkipMonitor}, 0, 0, 0)
registerSpecialCommand("Watch", 1, 0).
attachCommandExtra([]string{redisFlagNoScript, redisFlagFast}, 1, -1, 1)
}

View File

@@ -0,0 +1,20 @@
package database
import (
"github.com/hdt3213/godis/lib/utils"
"github.com/hdt3213/godis/redis/connection"
"github.com/hdt3213/godis/redis/protocol/asserts"
"testing"
)
func TestCommandInfo(t *testing.T) {
c := connection.NewFakeConn()
ret := testServer.Exec(c, utils.ToCmdLine("command"))
asserts.AssertNotError(t, ret)
ret = testServer.Exec(c, utils.ToCmdLine("command", "info", "mset"))
asserts.AssertNotError(t, ret)
ret = testServer.Exec(c, utils.ToCmdLine("command", "getkeys", "mset", "a", "a", "b", "b"))
asserts.AssertMultiBulkReply(t, ret, []string{"a", "b"})
ret = testServer.Exec(c, utils.ToCmdLine("command", "foobar"))
asserts.AssertErrReply(t, ret, "Unknown subcommand or wrong number of arguments for 'foobar'")
}

View File

@@ -11,7 +11,7 @@ Server.Exec is the main entry for Server, it handles authentication, publish-sub
[godis.DB.Exec](https://github.com/HDT3213/godis/blob/master/database/single_db.go) handles transaction control command (such as watch, multi, exec) itself, and invokes DB.execNormalCommand to handle normal commands. The word, normal command, is commands which read or write limited keys, can execute within transaction, and supports rollback. For example, get, set, lpush are normal commands, while flushdb, keys are not. [godis.DB.Exec](https://github.com/HDT3213/godis/blob/master/database/single_db.go) handles transaction control command (such as watch, multi, exec) itself, and invokes DB.execNormalCommand to handle normal commands. The word, normal command, is commands which read or write limited keys, can execute within transaction, and supports rollback. For example, get, set, lpush are normal commands, while flushdb, keys are not.
[RegisterCommand](https://github.com/HDT3213/godis/blob/master/database/router.go) is used for registering normal command. A normal command requires three functions [registerCommand](https://github.com/HDT3213/godis/blob/master/database/router.go) is used for registering normal command. A normal command requires three functions
- ExecFunc: The function that actually executes the command, such as [execHSet](https://github.com/HDT3213/godis/blob/master/database/hash.go) - ExecFunc: The function that actually executes the command, such as [execHSet](https://github.com/HDT3213/godis/blob/master/database/hash.go)
- PrepareFunc executes before ExecFunc, it analysises command line and returns read/written keys for lock - PrepareFunc executes before ExecFunc, it analysises command line and returns read/written keys for lock

View File

@@ -262,20 +262,16 @@ func geoRadius0(sortedSet *sortedset.SortedSet, lat float64, lng float64, radius
} }
func init() { func init() {
RegisterCommand("GeoAdd", execGeoAdd, writeFirstKey, undoGeoAdd, -5, flagWrite) registerCommand("GeoAdd", execGeoAdd, writeFirstKey, undoGeoAdd, -5, flagWrite).
RegisterCommand("GeoPos", execGeoPos, readFirstKey, nil, -2, flagReadOnly) attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM}, 1, 1, 1)
RegisterCommand("GeoDist", execGeoDist, readFirstKey, nil, -4, flagReadOnly) registerCommand("GeoPos", execGeoPos, readFirstKey, nil, -2, flagReadOnly).
RegisterCommand("GeoHash", execGeoHash, readFirstKey, nil, -2, flagReadOnly) attachCommandExtra([]string{redisFlagReadonly}, 1, 1, 1)
RegisterCommand("GeoRadius", execGeoRadius, readFirstKey, nil, -6, flagReadOnly) registerCommand("GeoDist", execGeoDist, readFirstKey, nil, -4, flagReadOnly).
RegisterCommand("GeoRadiusByMember", execGeoRadiusByMember, readFirstKey, nil, -5, flagReadOnly) attachCommandExtra([]string{redisFlagReadonly}, 1, 1, 1)
} registerCommand("GeoHash", execGeoHash, readFirstKey, nil, -2, flagReadOnly).
attachCommandExtra([]string{redisFlagReadonly}, 1, 1, 1)
func init() { registerCommand("GeoRadius", execGeoRadius, readFirstKey, nil, -6, flagReadOnly).
RegisterGodisCommand("GeoAdd", -5, []string{Write, Denyoom}, 1, 1, 1, writeFirstKey) attachCommandExtra([]string{redisFlagWrite, redisFlagMovableKeys}, 1, 1, 1)
RegisterGodisCommand("GeoPos", -2, []string{Readonly}, 1, 1, 1, readFirstKey) registerCommand("GeoRadiusByMember", execGeoRadiusByMember, readFirstKey, nil, -5, flagReadOnly).
RegisterGodisCommand("GeoDist", -4, []string{Readonly}, 1, 1, 1, readFirstKey) attachCommandExtra([]string{redisFlagWrite, redisFlagMovableKeys}, 1, 1, 1)
RegisterGodisCommand("GeoHash", -2, []string{Readonly}, 1, 1, 1, readFirstKey)
RegisterGodisCommand("GeoRadius", -6, []string{Write, Movablekeys}, 1, 1, 1, readFirstKey)
RegisterGodisCommand("GeoRadiusByMember", -5, []string{Write, Movablekeys}, 1, 1, 1, readFirstKey)
} }

View File

@@ -498,39 +498,36 @@ func execHRandField(db *DB, args [][]byte) redis.Reply {
} }
func init() { func init() {
RegisterCommand("HSet", execHSet, writeFirstKey, undoHSet, 4, flagWrite) registerCommand("HSet", execHSet, writeFirstKey, undoHSet, 4, flagWrite).
RegisterCommand("HSetNX", execHSetNX, writeFirstKey, undoHSet, 4, flagWrite) attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM, redisFlagFast}, 1, 1, 1)
RegisterCommand("HGet", execHGet, readFirstKey, nil, 3, flagReadOnly) registerCommand("HSetNX", execHSetNX, writeFirstKey, undoHSet, 4, flagWrite).
RegisterCommand("HExists", execHExists, readFirstKey, nil, 3, flagReadOnly) attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM, redisFlagFast}, 1, 1, 1)
RegisterCommand("HDel", execHDel, writeFirstKey, undoHDel, -3, flagWrite) registerCommand("HGet", execHGet, readFirstKey, nil, 3, flagReadOnly).
RegisterCommand("HLen", execHLen, readFirstKey, nil, 2, flagReadOnly) attachCommandExtra([]string{redisFlagReadonly, redisFlagFast}, 1, 1, 1)
RegisterCommand("HStrlen", execHStrlen, readFirstKey, nil, 3, flagReadOnly) registerCommand("HExists", execHExists, readFirstKey, nil, 3, flagReadOnly).
RegisterCommand("HMSet", execHMSet, writeFirstKey, undoHMSet, -4, flagWrite) attachCommandExtra([]string{redisFlagReadonly, redisFlagFast}, 1, 1, 1)
RegisterCommand("HMGet", execHMGet, readFirstKey, nil, -3, flagReadOnly) registerCommand("HDel", execHDel, writeFirstKey, undoHDel, -3, flagWrite).
RegisterCommand("HGet", execHGet, readFirstKey, nil, -3, flagReadOnly) attachCommandExtra([]string{redisFlagWrite, redisFlagFast}, 1, 1, 1)
RegisterCommand("HKeys", execHKeys, readFirstKey, nil, 2, flagReadOnly) registerCommand("HLen", execHLen, readFirstKey, nil, 2, flagReadOnly).
RegisterCommand("HVals", execHVals, readFirstKey, nil, 2, flagReadOnly) attachCommandExtra([]string{redisFlagReadonly, redisFlagFast}, 1, 1, 1)
RegisterCommand("HGetAll", execHGetAll, readFirstKey, nil, 2, flagReadOnly) registerCommand("HStrlen", execHStrlen, readFirstKey, nil, 3, flagReadOnly).
RegisterCommand("HIncrBy", execHIncrBy, writeFirstKey, undoHIncr, 4, flagWrite) attachCommandExtra([]string{redisFlagReadonly, redisFlagFast}, 1, 1, 1)
RegisterCommand("HIncrByFloat", execHIncrByFloat, writeFirstKey, undoHIncr, 4, flagWrite) registerCommand("HMSet", execHMSet, writeFirstKey, undoHMSet, -4, flagWrite).
RegisterCommand("HRandField", execHRandField, readFirstKey, nil, -2, flagReadOnly) attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM, redisFlagFast}, 1, 1, 1)
} registerCommand("HMGet", execHMGet, readFirstKey, nil, -3, flagReadOnly).
attachCommandExtra([]string{redisFlagReadonly, redisFlagFast}, 1, 1, 1)
func init() { registerCommand("HGet", execHGet, readFirstKey, nil, -3, flagReadOnly).
RegisterGodisCommand("HSet", 4, []string{Write, Denyoom, Fast}, 1, 1, 1, writeFirstKey) attachCommandExtra([]string{redisFlagReadonly, redisFlagFast}, 1, 1, 1)
RegisterGodisCommand("HSetNX", 4, []string{Write, Denyoom, Fast}, 1, 1, 1, writeFirstKey) registerCommand("HKeys", execHKeys, readFirstKey, nil, 2, flagReadOnly).
RegisterGodisCommand("HGet", 3, []string{Readonly, Fast}, 1, 1, 1, readFirstKey) attachCommandExtra([]string{redisFlagReadonly, redisFlagSortForScript}, 1, 1, 1)
RegisterGodisCommand("HExists", 3, []string{Readonly, Fast}, 1, 1, 1, readAllKeys) registerCommand("HVals", execHVals, readFirstKey, nil, 2, flagReadOnly).
RegisterGodisCommand("HDel", -3, []string{Write, Fast}, 1, 1, 1, writeFirstKey) attachCommandExtra([]string{redisFlagReadonly, redisFlagSortForScript}, 1, 1, 1)
RegisterGodisCommand("HLen", 2, []string{Readonly, Fast}, 1, 1, 1, readFirstKey) registerCommand("HGetAll", execHGetAll, readFirstKey, nil, 2, flagReadOnly).
RegisterGodisCommand("HStrlen", 3, []string{Readonly, Fast}, 1, 1, 1, readFirstKey) attachCommandExtra([]string{redisFlagReadonly, redisFlagRandom}, 1, 1, 1)
RegisterGodisCommand("HMSet", -1, []string{Write, Denyoom, Fast}, 1, 1, 1, writeFirstKey) registerCommand("HIncrBy", execHIncrBy, writeFirstKey, undoHIncr, 4, flagWrite).
RegisterGodisCommand("HMGet", -3, []string{Readonly, Fast}, 1, 1, 1, readFirstKey) attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM, redisFlagFast}, 1, 1, 1)
RegisterGodisCommand("HGet", -3, []string{Readonly, Fast}, 1, 1, 1, readFirstKey) registerCommand("HIncrByFloat", execHIncrByFloat, writeFirstKey, undoHIncr, 4, flagWrite).
RegisterGodisCommand("HKeys", 2, []string{Readonly, SortForScript}, 1, 1, 1, readFirstKey) attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM, redisFlagFast}, 1, 1, 1)
RegisterGodisCommand("HVals", 2, []string{Readonly, SortForScript}, 1, 1, 1, readFirstKey) registerCommand("HRandField", execHRandField, readFirstKey, nil, -2, flagReadOnly).
RegisterGodisCommand("HGetAll", 2, []string{Readonly, Random}, 1, 1, 1, readFirstKey) attachCommandExtra([]string{redisFlagRandom, redisFlagReadonly}, 1, 1, 1)
RegisterGodisCommand("HIncrBy", 4, []string{Write, Denyoom, Fast}, 1, 1, 1, writeFirstKey)
RegisterGodisCommand("HIncrByFloat", 4, []string{Write, Denyoom, Fast}, 1, 1, 1, writeFirstKey)
RegisterGodisCommand("HRandField", -2, []string{Random, Readonly}, 1, 1, 1, readFirstKey)
} }

View File

@@ -410,37 +410,34 @@ func execCopy(mdb *Server, conn redis.Connection, args [][]byte) redis.Reply {
} }
func init() { func init() {
RegisterCommand("Del", execDel, writeAllKeys, undoDel, -2, flagWrite) registerCommand("Del", execDel, writeAllKeys, undoDel, -2, flagWrite).
RegisterCommand("Expire", execExpire, writeFirstKey, undoExpire, 3, flagWrite) attachCommandExtra([]string{redisFlagWrite}, 1, -1, 1)
RegisterCommand("ExpireAt", execExpireAt, writeFirstKey, undoExpire, 3, flagWrite) registerCommand("Expire", execExpire, writeFirstKey, undoExpire, 3, flagWrite).
RegisterCommand("ExpireTime", execExpireTime, readFirstKey, nil, 2, flagReadOnly) attachCommandExtra([]string{redisFlagWrite, redisFlagFast}, 1, 1, 1)
RegisterCommand("PExpire", execPExpire, writeFirstKey, undoExpire, 3, flagWrite) registerCommand("ExpireAt", execExpireAt, writeFirstKey, undoExpire, 3, flagWrite).
RegisterCommand("PExpireAt", execPExpireAt, writeFirstKey, undoExpire, 3, flagWrite) attachCommandExtra([]string{redisFlagWrite, redisFlagFast}, 1, 1, 1)
RegisterCommand("PExpireTime", execPExpireTime, readFirstKey, nil, 2, flagReadOnly) registerCommand("ExpireTime", execExpireTime, readFirstKey, nil, 2, flagReadOnly).
RegisterCommand("TTL", execTTL, readFirstKey, nil, 2, flagReadOnly) attachCommandExtra([]string{redisFlagWrite, redisFlagFast}, 1, 1, 1)
RegisterCommand("PTTL", execPTTL, readFirstKey, nil, 2, flagReadOnly) registerCommand("PExpire", execPExpire, writeFirstKey, undoExpire, 3, flagWrite).
RegisterCommand("Persist", execPersist, writeFirstKey, undoExpire, 2, flagWrite) attachCommandExtra([]string{redisFlagWrite, redisFlagFast}, 1, 1, 1)
RegisterCommand("Exists", execExists, readAllKeys, nil, -2, flagReadOnly) registerCommand("PExpireAt", execPExpireAt, writeFirstKey, undoExpire, 3, flagWrite).
RegisterCommand("Type", execType, readFirstKey, nil, 2, flagReadOnly) attachCommandExtra([]string{redisFlagWrite, redisFlagFast}, 1, 1, 1)
RegisterCommand("Rename", execRename, prepareRename, undoRename, 3, flagReadOnly) registerCommand("PExpireTime", execPExpireTime, readFirstKey, nil, 2, flagReadOnly).
RegisterCommand("RenameNx", execRenameNx, prepareRename, undoRename, 3, flagReadOnly) attachCommandExtra([]string{redisFlagWrite, redisFlagFast}, 1, 1, 1)
RegisterCommand("Keys", execKeys, noPrepare, nil, 2, flagReadOnly) registerCommand("TTL", execTTL, readFirstKey, nil, 2, flagReadOnly).
} attachCommandExtra([]string{redisFlagReadonly, redisFlagRandom, redisFlagFast}, 1, 1, 1)
registerCommand("PTTL", execPTTL, readFirstKey, nil, 2, flagReadOnly).
func init() { attachCommandExtra([]string{redisFlagReadonly, redisFlagRandom, redisFlagFast}, 1, 1, 1)
RegisterGodisCommand("Del", -2, []string{Write}, 1, -1, 1, writeAllKeys) registerCommand("Persist", execPersist, writeFirstKey, undoExpire, 2, flagWrite).
RegisterGodisCommand("Expire", 3, []string{Write, Fast}, 1, 1, 1, writeFirstKey) attachCommandExtra([]string{redisFlagWrite, redisFlagFast}, 1, 1, 1)
RegisterGodisCommand("ExpireAt", 3, []string{Write, Fast}, 1, 1, 1, writeFirstKey) registerCommand("Exists", execExists, readAllKeys, nil, -2, flagReadOnly).
RegisterGodisCommand("ExpireTime", 2, []string{Write, Fast}, 1, 1, 1, readFirstKey) attachCommandExtra([]string{redisFlagReadonly, redisFlagFast}, 1, 1, 1)
RegisterGodisCommand("PExpire", 3, []string{Write, Fast}, 1, 1, 1, writeFirstKey) registerCommand("Type", execType, readFirstKey, nil, 2, flagReadOnly).
RegisterGodisCommand("PExpireAt", 3, []string{Write, Fast}, 1, 1, 1, writeFirstKey) attachCommandExtra([]string{redisFlagReadonly, redisFlagFast}, 1, 1, 1)
RegisterGodisCommand("PExpireTime", 2, []string{Write, Fast}, 1, 1, 1, readFirstKey) registerCommand("Rename", execRename, prepareRename, undoRename, 3, flagReadOnly).
RegisterGodisCommand("TTL", 2, []string{Readonly, Random, Fast}, 1, 1, 1, readFirstKey) attachCommandExtra([]string{redisFlagWrite}, 1, 1, 1)
RegisterGodisCommand("PTTL", 2, []string{Readonly, Random, Fast}, 1, 1, 1, readFirstKey) registerCommand("RenameNx", execRenameNx, prepareRename, undoRename, 3, flagReadOnly).
RegisterGodisCommand("Persist", 2, []string{Write, Fast}, 1, 1, 1, writeFirstKey) attachCommandExtra([]string{redisFlagWrite, redisFlagFast}, 1, 1, 1)
RegisterGodisCommand("Exists", -2, []string{Readonly, Fast}, 1, 1, 1, readAllKeys) registerCommand("Keys", execKeys, noPrepare, nil, 2, flagReadOnly).
RegisterGodisCommand("Type", 2, []string{Readonly, Fast}, 1, 1, 1, readFirstKey) attachCommandExtra([]string{redisFlagReadonly, redisFlagSortForScript}, 1, 1, 1)
RegisterGodisCommand("Rename", 3, []string{Write}, 1, 1, 1, prepareRename)
RegisterGodisCommand("RenameNx", 3, []string{Write, Fast}, 1, 1, 1, prepareRename)
RegisterGodisCommand("Keys", 2, []string{Readonly, SortForScript}, 1, 1, 1, nil)
} }

View File

@@ -511,31 +511,28 @@ func execRPushX(db *DB, args [][]byte) redis.Reply {
} }
func init() { func init() {
RegisterCommand("LPush", execLPush, writeFirstKey, undoLPush, -3, flagWrite) registerCommand("LPush", execLPush, writeFirstKey, undoLPush, -3, flagWrite).
RegisterCommand("LPushX", execLPushX, writeFirstKey, undoLPush, -3, flagWrite) attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM, redisFlagFast}, 1, 1, 1)
RegisterCommand("RPush", execRPush, writeFirstKey, undoRPush, -3, flagWrite) registerCommand("LPushX", execLPushX, writeFirstKey, undoLPush, -3, flagWrite).
RegisterCommand("RPushX", execRPushX, writeFirstKey, undoRPush, -3, flagWrite) attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM, redisFlagFast}, 1, 1, 1)
RegisterCommand("LPop", execLPop, writeFirstKey, undoLPop, 2, flagWrite) registerCommand("RPush", execRPush, writeFirstKey, undoRPush, -3, flagWrite).
RegisterCommand("RPop", execRPop, writeFirstKey, undoRPop, 2, flagWrite) attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM, redisFlagFast}, 1, 1, 1)
RegisterCommand("RPopLPush", execRPopLPush, prepareRPopLPush, undoRPopLPush, 3, flagWrite) registerCommand("RPushX", execRPushX, writeFirstKey, undoRPush, -3, flagWrite).
RegisterCommand("LRem", execLRem, writeFirstKey, rollbackFirstKey, 4, flagWrite) attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM, redisFlagFast}, 1, 1, 1)
RegisterCommand("LLen", execLLen, readFirstKey, nil, 2, flagReadOnly) registerCommand("LPop", execLPop, writeFirstKey, undoLPop, 2, flagWrite).
RegisterCommand("LIndex", execLIndex, readFirstKey, nil, 3, flagReadOnly) attachCommandExtra([]string{redisFlagWrite, redisFlagFast}, 1, 1, 1)
RegisterCommand("LSet", execLSet, writeFirstKey, undoLSet, 4, flagWrite) registerCommand("RPop", execRPop, writeFirstKey, undoRPop, 2, flagWrite).
RegisterCommand("LRange", execLRange, readFirstKey, nil, 4, flagReadOnly) attachCommandExtra([]string{redisFlagWrite, redisFlagFast}, 1, 1, 1)
} registerCommand("RPopLPush", execRPopLPush, prepareRPopLPush, undoRPopLPush, 3, flagWrite).
attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM}, 1, 1, 1)
func init() { registerCommand("LRem", execLRem, writeFirstKey, rollbackFirstKey, 4, flagWrite).
RegisterGodisCommand("LPush", -3, []string{Write, Denyoom, Fast}, 1, 1, 1, writeFirstKey) attachCommandExtra([]string{redisFlagWrite}, 1, 1, 1)
RegisterGodisCommand("LPushX", -3, []string{Write, Denyoom, Fast}, 1, 1, 1, writeFirstKey) registerCommand("LLen", execLLen, readFirstKey, nil, 2, flagReadOnly).
RegisterGodisCommand("RPush", -3, []string{Write, Denyoom, Fast}, 1, 1, 1, writeFirstKey) attachCommandExtra([]string{redisFlagReadonly, redisFlagFast}, 1, 1, 1)
RegisterGodisCommand("RPushX", -3, []string{Write, Denyoom, Fast}, 1, 1, 1, writeFirstKey) registerCommand("LIndex", execLIndex, readFirstKey, nil, 3, flagReadOnly).
RegisterGodisCommand("LPop", 2, []string{Write, Fast}, 1, 1, 1, writeFirstKey) attachCommandExtra([]string{redisFlagReadonly}, 1, 1, 1)
RegisterGodisCommand("RPop", 2, []string{Write, Fast}, 1, 1, 1, writeFirstKey) registerCommand("LSet", execLSet, writeFirstKey, undoLSet, 4, flagWrite).
RegisterGodisCommand("RPopLPush", 3, []string{Write, Denyoom}, 1, 1, 1, prepareRPopLPush) attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM}, 1, 1, 1)
RegisterGodisCommand("LRem", 4, []string{Write}, 1, 1, 1, writeFirstKey) registerCommand("LRange", execLRange, readFirstKey, nil, 4, flagReadOnly).
RegisterGodisCommand("LLen", 2, []string{Readonly, Fast}, 1, 1, 1, readFirstKey) attachCommandExtra([]string{redisFlagReadonly}, 1, 1, 1)
RegisterGodisCommand("LIndex", 3, []string{Readonly}, 1, 1, 1, readFirstKey)
RegisterGodisCommand("LSet", 4, []string{Write, Denyoom}, 1, 1, 1, writeFirstKey)
RegisterGodisCommand("LRange", 4, []string{Readonly}, 1, 1, 1, readFirstKey)
} }

View File

@@ -1,36 +1,67 @@
package database package database
import ( import (
"github.com/hdt3213/godis/interface/redis"
"github.com/hdt3213/godis/redis/protocol"
"strings" "strings"
) )
var cmdTable = make(map[string]*command) var cmdTable = make(map[string]*command)
type command struct { type command struct {
name string
executor ExecFunc executor ExecFunc
prepare PreFunc // return related keys command // prepare returns related keys command
undo UndoFunc prepare PreFunc
arity int // allow number of args, arity < 0 means len(args) >= -arity // undo generates undo-log before command actually executed, in case the command needs to be rolled back
flags int undo UndoFunc
// arity means allowed number of cmdArgs, arity < 0 means len(args) >= -arity.
// for example: the arity of `get` is 2, `mget` is -2
arity int
flags int
extra *commandExtra
} }
type commandExtra struct {
signs []string
firstKey int
lastKey int
keyStep int
}
const flagWrite = 0
const ( const (
flagWrite = 0 flagReadOnly = 1 << iota
flagReadOnly = 1 flagSpecial // command invoked in Exec
) )
// RegisterCommand registers a new command // registerCommand registers a normal command, which only read or modify a limited number of keys
// arity means allowed number of cmdArgs, arity < 0 means len(args) >= -arity. func registerCommand(name string, executor ExecFunc, prepare PreFunc, rollback UndoFunc, arity int, flags int) *command {
// for example: the arity of `get` is 2, `mget` is -2
func RegisterCommand(name string, executor ExecFunc, prepare PreFunc, rollback UndoFunc, arity int, flags int) {
name = strings.ToLower(name) name = strings.ToLower(name)
cmdTable[name] = &command{ cmd := &command{
name: name,
executor: executor, executor: executor,
prepare: prepare, prepare: prepare,
undo: rollback, undo: rollback,
arity: arity, arity: arity,
flags: flags, flags: flags,
} }
cmdTable[name] = cmd
return cmd
}
// registerSpecialCommand registers a special command, such as publish, select, keys, flushAll
func registerSpecialCommand(name string, arity int, flags int) *command {
name = strings.ToLower(name)
flags |= flagSpecial
cmd := &command{
name: name,
arity: arity,
flags: flags,
}
cmdTable[name] = cmd
return cmd
} }
func isReadOnlyCommand(name string) bool { func isReadOnlyCommand(name string) bool {
@@ -41,3 +72,32 @@ func isReadOnlyCommand(name string) bool {
} }
return cmd.flags&flagReadOnly > 0 return cmd.flags&flagReadOnly > 0
} }
func (cmd *command) toDescReply() redis.Reply {
args := make([]redis.Reply, 0, 6)
args = append(args,
protocol.MakeBulkReply([]byte(cmd.name)),
protocol.MakeIntReply(int64(cmd.arity)))
if cmd.extra != nil {
signs := make([][]byte, len(cmd.extra.signs))
for i, v := range cmd.extra.signs {
signs[i] = []byte(v)
}
args = append(args,
protocol.MakeMultiBulkReply(signs),
protocol.MakeIntReply(int64(cmd.extra.firstKey)),
protocol.MakeIntReply(int64(cmd.extra.lastKey)),
protocol.MakeIntReply(int64(cmd.extra.keyStep)),
)
}
return protocol.MakeMultiRawReply(args)
}
func (cmd *command) attachCommandExtra(signs []string, firstKey int, lastKey int, keyStep int) {
cmd.extra = &commandExtra{
signs: signs,
firstKey: firstKey,
lastKey: lastKey,
keyStep: keyStep,
}
}

View File

@@ -94,13 +94,13 @@ func (server *Server) Exec(c redis.Connection, cmdLine [][]byte) (result redis.R
if cmdName == "auth" { if cmdName == "auth" {
return Auth(c, cmdLine[1:]) return Auth(c, cmdLine[1:])
} }
if !isAuthenticated(c) {
return protocol.MakeErrReply("NOAUTH Authentication required")
}
// info // info
if cmdName == "info" { if cmdName == "info" {
return Info(c, cmdLine) return Info(c, cmdLine)
} }
if !isAuthenticated(c) {
return protocol.MakeErrReply("NOAUTH Authentication required")
}
if cmdName == "slaveof" { if cmdName == "slaveof" {
if c != nil && c.InMultiState() { if c != nil && c.InMultiState() {
return protocol.MakeErrReply("cannot use slave of database within multi") return protocol.MakeErrReply("cannot use slave of database within multi")

View File

@@ -479,33 +479,30 @@ func execSRandMember(db *DB, args [][]byte) redis.Reply {
} }
func init() { func init() {
RegisterCommand("SAdd", execSAdd, writeFirstKey, undoSetChange, -3, flagWrite) registerCommand("SAdd", execSAdd, writeFirstKey, undoSetChange, -3, flagWrite).
RegisterCommand("SIsMember", execSIsMember, readFirstKey, nil, 3, flagReadOnly) attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM, redisFlagFast}, 1, 1, 1)
RegisterCommand("SRem", execSRem, writeFirstKey, undoSetChange, -3, flagWrite) registerCommand("SIsMember", execSIsMember, readFirstKey, nil, 3, flagReadOnly).
RegisterCommand("SPop", execSPop, writeFirstKey, undoSetChange, -2, flagWrite) attachCommandExtra([]string{redisFlagReadonly, redisFlagFast}, 1, 1, 1)
RegisterCommand("SCard", execSCard, readFirstKey, nil, 2, flagReadOnly) registerCommand("SRem", execSRem, writeFirstKey, undoSetChange, -3, flagWrite).
RegisterCommand("SMembers", execSMembers, readFirstKey, nil, 2, flagReadOnly) attachCommandExtra([]string{redisFlagWrite, redisFlagFast}, 1, 1, 1)
RegisterCommand("SInter", execSInter, prepareSetCalculate, nil, -2, flagReadOnly) registerCommand("SPop", execSPop, writeFirstKey, undoSetChange, -2, flagWrite).
RegisterCommand("SInterStore", execSInterStore, prepareSetCalculateStore, rollbackFirstKey, -3, flagWrite) attachCommandExtra([]string{redisFlagWrite, redisFlagRandom, redisFlagFast}, 1, 1, 1)
RegisterCommand("SUnion", execSUnion, prepareSetCalculate, nil, -2, flagReadOnly) registerCommand("SCard", execSCard, readFirstKey, nil, 2, flagReadOnly).
RegisterCommand("SUnionStore", execSUnionStore, prepareSetCalculateStore, rollbackFirstKey, -3, flagWrite) attachCommandExtra([]string{redisFlagReadonly, redisFlagFast}, 1, 1, 1)
RegisterCommand("SDiff", execSDiff, prepareSetCalculate, nil, -2, flagReadOnly) registerCommand("SMembers", execSMembers, readFirstKey, nil, 2, flagReadOnly).
RegisterCommand("SDiffStore", execSDiffStore, prepareSetCalculateStore, rollbackFirstKey, -3, flagWrite) attachCommandExtra([]string{redisFlagReadonly, redisFlagSortForScript}, 1, 1, 1)
RegisterCommand("SRandMember", execSRandMember, readFirstKey, nil, -2, flagReadOnly) registerCommand("SInter", execSInter, prepareSetCalculate, nil, -2, flagReadOnly).
} attachCommandExtra([]string{redisFlagReadonly, redisFlagSortForScript}, 1, -1, 1)
registerCommand("SInterStore", execSInterStore, prepareSetCalculateStore, rollbackFirstKey, -3, flagWrite).
func init() { attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM}, 1, -1, 1)
RegisterGodisCommand("SAdd", -3, []string{Write, Denyoom, Fast}, 1, 1, 1, writeFirstKey) registerCommand("SUnion", execSUnion, prepareSetCalculate, nil, -2, flagReadOnly).
RegisterGodisCommand("SIsMember", 3, []string{Readonly, Fast}, 1, 1, 1, readFirstKey) attachCommandExtra([]string{redisFlagReadonly, redisFlagSortForScript}, 1, -1, 1)
RegisterGodisCommand("SRem", -3, []string{Write, Fast}, 1, 1, 1, writeFirstKey) registerCommand("SUnionStore", execSUnionStore, prepareSetCalculateStore, rollbackFirstKey, -3, flagWrite).
RegisterGodisCommand("SPop", -2, []string{Write, Random, Fast}, 1, 1, 1, writeFirstKey) attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM}, 1, -1, 1)
RegisterGodisCommand("SCard", 2, []string{Readonly, Fast}, 1, 1, 1, readFirstKey) registerCommand("SDiff", execSDiff, prepareSetCalculate, nil, -2, flagReadOnly).
RegisterGodisCommand("SMembers", 2, []string{Readonly, SortForScript}, 1, 1, 1, readFirstKey) attachCommandExtra([]string{redisFlagReadonly, redisFlagSortForScript}, 1, 1, 1)
RegisterGodisCommand("SInter", -2, []string{Readonly, SortForScript}, 1, -1, 1, prepareSetCalculate) registerCommand("SDiffStore", execSDiffStore, prepareSetCalculateStore, rollbackFirstKey, -3, flagWrite).
RegisterGodisCommand("SInterStore", -3, []string{Write, Denyoom}, 1, -1, 1, prepareSetCalculateStore) attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM}, 1, 1, 1)
RegisterGodisCommand("SUnion", -2, []string{Readonly, SortForScript}, 1, -1, 1, prepareSetCalculate) registerCommand("SRandMember", execSRandMember, readFirstKey, nil, -2, flagReadOnly).
RegisterGodisCommand("SUnionStore", -3, []string{Write, Denyoom}, 1, -1, 1, prepareSetCalculateStore) attachCommandExtra([]string{redisFlagReadonly, redisFlagRandom}, 1, 1, 1)
RegisterGodisCommand("SDiff", -2, []string{Readonly, SortForScript}, 1, 1, 1, prepareSetCalculate)
RegisterGodisCommand("SDiffStore", -3, []string{Write, Denyoom}, 1, 1, 1, prepareSetCalculateStore)
RegisterGodisCommand("SRandMember", -2, []string{Readonly, Random}, 1, 1, 1, readFirstKey)
} }

View File

@@ -622,37 +622,34 @@ func undoZIncr(db *DB, args [][]byte) []CmdLine {
} }
func init() { func init() {
RegisterCommand("ZAdd", execZAdd, writeFirstKey, undoZAdd, -4, flagWrite) registerCommand("ZAdd", execZAdd, writeFirstKey, undoZAdd, -4, flagWrite).
RegisterCommand("ZScore", execZScore, readFirstKey, nil, 3, flagReadOnly) attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM, redisFlagFast}, 1, 1, 1)
RegisterCommand("ZIncrBy", execZIncrBy, writeFirstKey, undoZIncr, 4, flagWrite) registerCommand("ZScore", execZScore, readFirstKey, nil, 3, flagReadOnly).
RegisterCommand("ZRank", execZRank, readFirstKey, nil, 3, flagReadOnly) attachCommandExtra([]string{redisFlagReadonly, redisFlagFast}, 1, 1, 1)
RegisterCommand("ZCount", execZCount, readFirstKey, nil, 4, flagReadOnly) registerCommand("ZIncrBy", execZIncrBy, writeFirstKey, undoZIncr, 4, flagWrite).
RegisterCommand("ZRevRank", execZRevRank, readFirstKey, nil, 3, flagReadOnly) attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM, redisFlagFast}, 1, 1, 1)
RegisterCommand("ZCard", execZCard, readFirstKey, nil, 2, flagReadOnly) registerCommand("ZRank", execZRank, readFirstKey, nil, 3, flagReadOnly).
RegisterCommand("ZRange", execZRange, readFirstKey, nil, -4, flagReadOnly) attachCommandExtra([]string{redisFlagReadonly, redisFlagFast}, 1, 1, 1)
RegisterCommand("ZRangeByScore", execZRangeByScore, readFirstKey, nil, -4, flagReadOnly) registerCommand("ZCount", execZCount, readFirstKey, nil, 4, flagReadOnly).
RegisterCommand("ZRevRange", execZRevRange, readFirstKey, nil, -4, flagReadOnly) attachCommandExtra([]string{redisFlagReadonly, redisFlagFast}, 1, 1, 1)
RegisterCommand("ZRevRangeByScore", execZRevRangeByScore, readFirstKey, nil, -4, flagReadOnly) registerCommand("ZRevRank", execZRevRank, readFirstKey, nil, 3, flagReadOnly).
RegisterCommand("ZPopMin", execZPopMin, writeFirstKey, rollbackFirstKey, -2, flagWrite) attachCommandExtra([]string{redisFlagReadonly, redisFlagFast}, 1, 1, 1)
RegisterCommand("ZRem", execZRem, writeFirstKey, undoZRem, -3, flagWrite) registerCommand("ZCard", execZCard, readFirstKey, nil, 2, flagReadOnly).
RegisterCommand("ZRemRangeByScore", execZRemRangeByScore, writeFirstKey, rollbackFirstKey, 4, flagWrite) attachCommandExtra([]string{redisFlagReadonly, redisFlagFast}, 1, 1, 1)
RegisterCommand("ZRemRangeByRank", execZRemRangeByRank, writeFirstKey, rollbackFirstKey, 4, flagWrite) registerCommand("ZRange", execZRange, readFirstKey, nil, -4, flagReadOnly).
} attachCommandExtra([]string{redisFlagReadonly}, 1, 1, 1)
registerCommand("ZRangeByScore", execZRangeByScore, readFirstKey, nil, -4, flagReadOnly).
func init() { attachCommandExtra([]string{redisFlagReadonly}, 1, 1, 1)
RegisterGodisCommand("ZAdd", -4, []string{Write, Denyoom, Fast}, 1, 1, 1, writeFirstKey) registerCommand("ZRevRange", execZRevRange, readFirstKey, nil, -4, flagReadOnly).
RegisterGodisCommand("ZScore", 3, []string{Readonly, Fast}, 1, 1, 1, readFirstKey) attachCommandExtra([]string{redisFlagReadonly}, 1, 1, 1)
RegisterGodisCommand("ZIncrBy", 4, []string{Write, Denyoom, Fast}, 1, 1, 1, writeFirstKey) registerCommand("ZRevRangeByScore", execZRevRangeByScore, readFirstKey, nil, -4, flagReadOnly).
RegisterGodisCommand("ZRank", 3, []string{Readonly, Fast}, 1, 1, 1, readFirstKey) attachCommandExtra([]string{redisFlagReadonly}, 1, 1, 1)
RegisterGodisCommand("ZCount", 4, []string{Readonly, Fast}, 1, 1, 1, readFirstKey) registerCommand("ZPopMin", execZPopMin, writeFirstKey, rollbackFirstKey, -2, flagWrite).
RegisterGodisCommand("ZRevRank", 3, []string{Readonly, Fast}, 1, 1, 1, readFirstKey) attachCommandExtra([]string{redisFlagWrite, redisFlagFast}, 1, 1, 1)
RegisterGodisCommand("ZCard", 2, []string{Readonly, Fast}, 1, 1, 1, readFirstKey) registerCommand("ZRem", execZRem, writeFirstKey, undoZRem, -3, flagWrite).
RegisterGodisCommand("ZRange", -4, []string{Readonly}, 1, 1, 1, readFirstKey) attachCommandExtra([]string{redisFlagWrite, redisFlagFast}, 1, 1, 1)
RegisterGodisCommand("ZRangeByScore", -4, []string{Readonly}, 1, 1, 1, readFirstKey) registerCommand("ZRemRangeByScore", execZRemRangeByScore, writeFirstKey, rollbackFirstKey, 4, flagWrite).
RegisterGodisCommand("ZRevRange", -4, []string{Readonly}, 1, 1, 1, readFirstKey) attachCommandExtra([]string{redisFlagWrite}, 1, 1, 1)
RegisterGodisCommand("ZRevRangeByScore", -4, []string{Readonly}, 1, 1, 1, readFirstKey) registerCommand("ZRemRangeByRank", execZRemRangeByRank, writeFirstKey, rollbackFirstKey, 4, flagWrite).
RegisterGodisCommand("ZPopMin", -2, []string{Write, Fast}, 1, 1, 1, writeFirstKey) attachCommandExtra([]string{redisFlagWrite}, 1, 1, 1)
RegisterGodisCommand("ZRem", -3, []string{Write, Fast}, 1, 1, 1, writeFirstKey)
RegisterGodisCommand("ZRemRangeByScore", 4, []string{Write}, 1, 1, 1, writeFirstKey)
RegisterGodisCommand("ZRemRangeByRank", 4, []string{Write}, 1, 1, 1, writeFirstKey)
} }

View File

@@ -837,59 +837,53 @@ func getRandomKey(db *DB, args [][]byte) redis.Reply {
} }
func init() { func init() {
RegisterCommand("Set", execSet, writeFirstKey, rollbackFirstKey, -3, flagWrite) registerCommand("Set", execSet, writeFirstKey, rollbackFirstKey, -3, flagWrite).
RegisterCommand("SetNx", execSetNX, writeFirstKey, rollbackFirstKey, 3, flagWrite) attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM}, 1, 1, 1)
RegisterCommand("SetEX", execSetEX, writeFirstKey, rollbackFirstKey, 4, flagWrite) registerCommand("SetNx", execSetNX, writeFirstKey, rollbackFirstKey, 3, flagWrite).
RegisterCommand("PSetEX", execPSetEX, writeFirstKey, rollbackFirstKey, 4, flagWrite) attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM, redisFlagFast}, 1, 1, 1)
RegisterCommand("MSet", execMSet, prepareMSet, undoMSet, -3, flagWrite) registerCommand("SetEX", execSetEX, writeFirstKey, rollbackFirstKey, 4, flagWrite).
RegisterCommand("MGet", execMGet, prepareMGet, nil, -2, flagReadOnly) attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM}, 1, 1, 1)
RegisterCommand("MSetNX", execMSetNX, prepareMSet, undoMSet, -3, flagWrite) registerCommand("PSetEX", execPSetEX, writeFirstKey, rollbackFirstKey, 4, flagWrite).
RegisterCommand("Get", execGet, readFirstKey, nil, 2, flagReadOnly) attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM}, 1, 1, 1)
RegisterCommand("GetEX", execGetEX, writeFirstKey, rollbackFirstKey, -2, flagReadOnly) registerCommand("MSet", execMSet, prepareMSet, undoMSet, -3, flagWrite).
RegisterCommand("GetSet", execGetSet, writeFirstKey, rollbackFirstKey, 3, flagWrite) attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM}, 1, -1, 2)
RegisterCommand("GetDel", execGetDel, writeFirstKey, rollbackFirstKey, 2, flagWrite) registerCommand("MGet", execMGet, prepareMGet, nil, -2, flagReadOnly).
RegisterCommand("Incr", execIncr, writeFirstKey, rollbackFirstKey, 2, flagWrite) attachCommandExtra([]string{redisFlagReadonly, redisFlagFast}, 1, 1, 1)
RegisterCommand("IncrBy", execIncrBy, writeFirstKey, rollbackFirstKey, 3, flagWrite) registerCommand("MSetNX", execMSetNX, prepareMSet, undoMSet, -3, flagWrite).
RegisterCommand("IncrByFloat", execIncrByFloat, writeFirstKey, rollbackFirstKey, 3, flagWrite) attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM}, 1, 1, 1)
RegisterCommand("Decr", execDecr, writeFirstKey, rollbackFirstKey, 2, flagWrite) registerCommand("Get", execGet, readFirstKey, nil, 2, flagReadOnly).
RegisterCommand("DecrBy", execDecrBy, writeFirstKey, rollbackFirstKey, 3, flagWrite) attachCommandExtra([]string{redisFlagReadonly, redisFlagFast}, 1, 1, 1)
RegisterCommand("StrLen", execStrLen, readFirstKey, nil, 2, flagReadOnly) registerCommand("GetEX", execGetEX, writeFirstKey, rollbackFirstKey, -2, flagReadOnly).
RegisterCommand("Append", execAppend, writeFirstKey, rollbackFirstKey, 3, flagWrite) attachCommandExtra([]string{redisFlagReadonly, redisFlagFast}, 1, 1, 1)
RegisterCommand("SetRange", execSetRange, writeFirstKey, rollbackFirstKey, 4, flagWrite) registerCommand("GetSet", execGetSet, writeFirstKey, rollbackFirstKey, 3, flagWrite).
RegisterCommand("GetRange", execGetRange, readFirstKey, nil, 4, flagReadOnly) attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM}, 1, 1, 1)
RegisterCommand("SetBit", execSetBit, writeFirstKey, rollbackFirstKey, 4, flagWrite) registerCommand("GetDel", execGetDel, writeFirstKey, rollbackFirstKey, 2, flagWrite).
RegisterCommand("GetBit", execGetBit, readFirstKey, nil, 3, flagReadOnly) attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM}, 1, 1, 1)
RegisterCommand("BitCount", execBitCount, readFirstKey, nil, -2, flagReadOnly) registerCommand("Incr", execIncr, writeFirstKey, rollbackFirstKey, 2, flagWrite).
RegisterCommand("BitPos", execBitPos, readFirstKey, nil, -3, flagReadOnly) attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM, redisFlagFast}, 1, 1, 1)
RegisterCommand("Randomkey", getRandomKey, readAllKeys, nil, 1, flagReadOnly) registerCommand("IncrBy", execIncrBy, writeFirstKey, rollbackFirstKey, 3, flagWrite).
attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM}, 1, 1, 1)
} registerCommand("IncrByFloat", execIncrByFloat, writeFirstKey, rollbackFirstKey, 3, flagWrite).attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM}, 1, 1, 1)
registerCommand("Decr", execDecr, writeFirstKey, rollbackFirstKey, 2, flagWrite).
func init() { attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM}, 1, 1, 1)
RegisterGodisCommand("Set", -3, []string{Write, Denyoom}, 1, 1, 1, writeFirstKey) registerCommand("DecrBy", execDecrBy, writeFirstKey, rollbackFirstKey, 3, flagWrite).
RegisterGodisCommand("SetNx", 3, []string{Write, Denyoom, Fast}, 1, 1, 1, writeFirstKey) attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM}, 1, 1, 1)
RegisterGodisCommand("SetEX", 4, []string{Write, Denyoom}, 1, 1, 1, writeFirstKey) registerCommand("StrLen", execStrLen, readFirstKey, nil, 2, flagReadOnly).
RegisterGodisCommand("PSetEX", 4, []string{Write, Denyoom}, 1, 1, 1, writeFirstKey) attachCommandExtra([]string{redisFlagReadonly, redisFlagFast}, 1, 1, 1)
RegisterGodisCommand("MSet", -3, []string{Write, Denyoom}, 1, -1, 2, prepareMSet) registerCommand("Append", execAppend, writeFirstKey, rollbackFirstKey, 3, flagWrite).
RegisterGodisCommand("MGet", -2, []string{Readonly, Fast}, 1, 1, 1, prepareMSet) attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM}, 1, 1, 1)
RegisterGodisCommand("MSetNX", -3, []string{Write, Denyoom}, 1, 1, 1, prepareMSet) registerCommand("SetRange", execSetRange, writeFirstKey, rollbackFirstKey, 4, flagWrite).
RegisterGodisCommand("Get", 2, []string{Readonly, Fast}, 1, 1, 1, readFirstKey) attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM}, 1, 1, 1)
RegisterGodisCommand("GetEX", -2, []string{Readonly, Fast}, 1, 1, 1, writeFirstKey) registerCommand("GetRange", execGetRange, readFirstKey, nil, 4, flagReadOnly).
RegisterGodisCommand("GetSet", 3, []string{Write, Denyoom}, 1, 1, 1, writeFirstKey) attachCommandExtra([]string{redisFlagReadonly}, 1, 1, 1)
RegisterGodisCommand("GetDel", 2, []string{Write, Denyoom}, 1, 1, 1, writeFirstKey) registerCommand("SetBit", execSetBit, writeFirstKey, rollbackFirstKey, 4, flagWrite).
RegisterGodisCommand("Incr", 2, []string{Write, Denyoom, Fast}, 1, 1, 1, writeFirstKey) attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM}, 1, 1, 1)
RegisterGodisCommand("IncrBy", 3, []string{Write, Denyoom}, 1, 1, 1, writeFirstKey) registerCommand("GetBit", execGetBit, readFirstKey, nil, 3, flagReadOnly).
RegisterGodisCommand("IncrByFloat", 3, []string{Write, Denyoom}, 1, 1, 1, writeFirstKey) attachCommandExtra([]string{redisFlagReadonly, redisFlagFast}, 1, 1, 1)
RegisterGodisCommand("Decr", 2, []string{Write, Denyoom}, 1, 1, 1, writeFirstKey) registerCommand("BitCount", execBitCount, readFirstKey, nil, -2, flagReadOnly).
RegisterGodisCommand("DecrBy", 3, []string{Write, Denyoom}, 1, 1, 1, writeFirstKey) attachCommandExtra([]string{redisFlagReadonly}, 1, 1, 1)
RegisterGodisCommand("StrLen", 2, []string{Readonly, Fast}, 1, 1, 1, readFirstKey) registerCommand("BitPos", execBitPos, readFirstKey, nil, -3, flagReadOnly).
RegisterGodisCommand("Append", 3, []string{Write, Denyoom}, 1, 1, 1, writeFirstKey) attachCommandExtra([]string{redisFlagReadonly}, 1, 1, 1)
RegisterGodisCommand("SetRange", 4, []string{Write, Denyoom}, 1, 1, 1, writeFirstKey) registerCommand("Randomkey", getRandomKey, readAllKeys, nil, 1, flagReadOnly).
RegisterGodisCommand("GetRange", 4, []string{Readonly}, 1, 1, 1, readFirstKey) attachCommandExtra([]string{redisFlagReadonly, redisFlagRandom}, 1, 1, 1)
RegisterGodisCommand("SetBit", 4, []string{Write, Denyoom}, 1, 1, 1, writeFirstKey)
RegisterGodisCommand("GetBit", 3, []string{Readonly, Fast}, 1, 1, 1, readFirstKey)
RegisterGodisCommand("BitCount", -2, []string{Readonly}, 1, 1, 1, readFirstKey)
RegisterGodisCommand("BitPos", -3, []string{Readonly}, 1, 1, 1, readFirstKey)
RegisterGodisCommand("Randomkey", 1, []string{Readonly, Random}, 1, 1, 1, readAllKeys)
} }

View File

@@ -23,7 +23,7 @@ func execGetVersion(db *DB, args [][]byte) redis.Reply {
} }
func init() { func init() {
RegisterCommand("GetVer", execGetVersion, readAllKeys, nil, 2, flagReadOnly) registerCommand("GetVer", execGetVersion, readAllKeys, nil, 2, flagReadOnly)
} }
// invoker should lock watching keys // invoker should lock watching keys