diff --git a/database/cluster_helper.go b/database/cluster_helper.go index 986b0dc..e663c8e 100644 --- a/database/cluster_helper.go +++ b/database/cluster_helper.go @@ -129,11 +129,11 @@ func execCopyTo(db *DB, args [][]byte) redis.Reply { } func init() { - RegisterCommand("DumpKey", execDumpKey, writeAllKeys, undoDel, 2, flagReadOnly) - RegisterCommand("ExistIn", execExistIn, readAllKeys, nil, -1, flagReadOnly) - RegisterCommand("RenameFrom", execRenameFrom, readFirstKey, nil, 2, flagWrite) - RegisterCommand("RenameTo", execRenameTo, writeFirstKey, rollbackFirstKey, 4, flagWrite) - RegisterCommand("RenameNxTo", execRenameTo, writeFirstKey, rollbackFirstKey, 4, flagWrite) - RegisterCommand("CopyFrom", execCopyFrom, readFirstKey, nil, 2, flagReadOnly) - RegisterCommand("CopyTo", execCopyTo, writeFirstKey, rollbackFirstKey, 5, flagWrite) + registerCommand("DumpKey", execDumpKey, writeAllKeys, undoDel, 2, flagReadOnly) + registerCommand("ExistIn", execExistIn, readAllKeys, nil, -1, flagReadOnly) + registerCommand("RenameFrom", execRenameFrom, readFirstKey, nil, 2, flagWrite) + registerCommand("RenameTo", execRenameTo, writeFirstKey, rollbackFirstKey, 4, flagWrite) + registerCommand("RenameNxTo", execRenameTo, writeFirstKey, rollbackFirstKey, 4, flagWrite) + registerCommand("CopyFrom", execCopyFrom, readFirstKey, nil, 2, flagReadOnly) + registerCommand("CopyTo", execCopyTo, writeFirstKey, rollbackFirstKey, 5, flagWrite) } diff --git a/database/command.go b/database/command.go deleted file mode 100644 index ba2b772..0000000 --- a/database/command.go +++ /dev/null @@ -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) - -} diff --git a/database/commandinfo.go b/database/commandinfo.go new file mode 100644 index 0000000..020e4bb --- /dev/null +++ b/database/commandinfo.go @@ -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) +} diff --git a/database/commandinfo_test.go b/database/commandinfo_test.go new file mode 100644 index 0000000..26ba0da --- /dev/null +++ b/database/commandinfo_test.go @@ -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'") +} diff --git a/database/doc.go b/database/doc.go index 8fa863f..56a1029 100644 --- a/database/doc.go +++ b/database/doc.go @@ -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. -[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) - PrepareFunc executes before ExecFunc, it analysises command line and returns read/written keys for lock diff --git a/database/geo.go b/database/geo.go index 5c00c18..77fc45d 100644 --- a/database/geo.go +++ b/database/geo.go @@ -262,20 +262,16 @@ func geoRadius0(sortedSet *sortedset.SortedSet, lat float64, lng float64, radius } func init() { - RegisterCommand("GeoAdd", execGeoAdd, writeFirstKey, undoGeoAdd, -5, flagWrite) - RegisterCommand("GeoPos", execGeoPos, readFirstKey, nil, -2, flagReadOnly) - RegisterCommand("GeoDist", execGeoDist, readFirstKey, nil, -4, flagReadOnly) - RegisterCommand("GeoHash", execGeoHash, readFirstKey, nil, -2, flagReadOnly) - RegisterCommand("GeoRadius", execGeoRadius, readFirstKey, nil, -6, flagReadOnly) - RegisterCommand("GeoRadiusByMember", execGeoRadiusByMember, readFirstKey, nil, -5, flagReadOnly) -} - -func init() { - RegisterGodisCommand("GeoAdd", -5, []string{Write, Denyoom}, 1, 1, 1, writeFirstKey) - RegisterGodisCommand("GeoPos", -2, []string{Readonly}, 1, 1, 1, readFirstKey) - RegisterGodisCommand("GeoDist", -4, []string{Readonly}, 1, 1, 1, readFirstKey) - 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) - + registerCommand("GeoAdd", execGeoAdd, writeFirstKey, undoGeoAdd, -5, flagWrite). + attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM}, 1, 1, 1) + registerCommand("GeoPos", execGeoPos, readFirstKey, nil, -2, flagReadOnly). + attachCommandExtra([]string{redisFlagReadonly}, 1, 1, 1) + registerCommand("GeoDist", execGeoDist, readFirstKey, nil, -4, flagReadOnly). + attachCommandExtra([]string{redisFlagReadonly}, 1, 1, 1) + registerCommand("GeoHash", execGeoHash, readFirstKey, nil, -2, flagReadOnly). + attachCommandExtra([]string{redisFlagReadonly}, 1, 1, 1) + registerCommand("GeoRadius", execGeoRadius, readFirstKey, nil, -6, flagReadOnly). + attachCommandExtra([]string{redisFlagWrite, redisFlagMovableKeys}, 1, 1, 1) + registerCommand("GeoRadiusByMember", execGeoRadiusByMember, readFirstKey, nil, -5, flagReadOnly). + attachCommandExtra([]string{redisFlagWrite, redisFlagMovableKeys}, 1, 1, 1) } diff --git a/database/hash.go b/database/hash.go index d518061..6ca5256 100644 --- a/database/hash.go +++ b/database/hash.go @@ -498,39 +498,36 @@ func execHRandField(db *DB, args [][]byte) redis.Reply { } func init() { - RegisterCommand("HSet", execHSet, writeFirstKey, undoHSet, 4, flagWrite) - RegisterCommand("HSetNX", execHSetNX, writeFirstKey, undoHSet, 4, flagWrite) - RegisterCommand("HGet", execHGet, readFirstKey, nil, 3, flagReadOnly) - RegisterCommand("HExists", execHExists, readFirstKey, nil, 3, flagReadOnly) - RegisterCommand("HDel", execHDel, writeFirstKey, undoHDel, -3, flagWrite) - RegisterCommand("HLen", execHLen, readFirstKey, nil, 2, flagReadOnly) - RegisterCommand("HStrlen", execHStrlen, readFirstKey, nil, 3, flagReadOnly) - RegisterCommand("HMSet", execHMSet, writeFirstKey, undoHMSet, -4, flagWrite) - RegisterCommand("HMGet", execHMGet, readFirstKey, nil, -3, flagReadOnly) - RegisterCommand("HGet", execHGet, readFirstKey, nil, -3, flagReadOnly) - RegisterCommand("HKeys", execHKeys, readFirstKey, nil, 2, flagReadOnly) - RegisterCommand("HVals", execHVals, readFirstKey, nil, 2, flagReadOnly) - RegisterCommand("HGetAll", execHGetAll, readFirstKey, nil, 2, flagReadOnly) - RegisterCommand("HIncrBy", execHIncrBy, writeFirstKey, undoHIncr, 4, flagWrite) - RegisterCommand("HIncrByFloat", execHIncrByFloat, writeFirstKey, undoHIncr, 4, flagWrite) - RegisterCommand("HRandField", execHRandField, readFirstKey, nil, -2, flagReadOnly) -} - -func init() { - RegisterGodisCommand("HSet", 4, []string{Write, Denyoom, Fast}, 1, 1, 1, writeFirstKey) - RegisterGodisCommand("HSetNX", 4, []string{Write, Denyoom, Fast}, 1, 1, 1, writeFirstKey) - RegisterGodisCommand("HGet", 3, []string{Readonly, Fast}, 1, 1, 1, readFirstKey) - RegisterGodisCommand("HExists", 3, []string{Readonly, Fast}, 1, 1, 1, readAllKeys) - RegisterGodisCommand("HDel", -3, []string{Write, Fast}, 1, 1, 1, writeFirstKey) - RegisterGodisCommand("HLen", 2, []string{Readonly, Fast}, 1, 1, 1, readFirstKey) - RegisterGodisCommand("HStrlen", 3, []string{Readonly, Fast}, 1, 1, 1, readFirstKey) - RegisterGodisCommand("HMSet", -1, []string{Write, Denyoom, Fast}, 1, 1, 1, writeFirstKey) - RegisterGodisCommand("HMGet", -3, []string{Readonly, Fast}, 1, 1, 1, readFirstKey) - RegisterGodisCommand("HGet", -3, []string{Readonly, Fast}, 1, 1, 1, readFirstKey) - RegisterGodisCommand("HKeys", 2, []string{Readonly, SortForScript}, 1, 1, 1, readFirstKey) - RegisterGodisCommand("HVals", 2, []string{Readonly, SortForScript}, 1, 1, 1, readFirstKey) - RegisterGodisCommand("HGetAll", 2, []string{Readonly, Random}, 1, 1, 1, readFirstKey) - 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) + registerCommand("HSet", execHSet, writeFirstKey, undoHSet, 4, flagWrite). + attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM, redisFlagFast}, 1, 1, 1) + registerCommand("HSetNX", execHSetNX, writeFirstKey, undoHSet, 4, flagWrite). + attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM, redisFlagFast}, 1, 1, 1) + registerCommand("HGet", execHGet, readFirstKey, nil, 3, flagReadOnly). + attachCommandExtra([]string{redisFlagReadonly, redisFlagFast}, 1, 1, 1) + registerCommand("HExists", execHExists, readFirstKey, nil, 3, flagReadOnly). + attachCommandExtra([]string{redisFlagReadonly, redisFlagFast}, 1, 1, 1) + registerCommand("HDel", execHDel, writeFirstKey, undoHDel, -3, flagWrite). + attachCommandExtra([]string{redisFlagWrite, redisFlagFast}, 1, 1, 1) + registerCommand("HLen", execHLen, readFirstKey, nil, 2, flagReadOnly). + attachCommandExtra([]string{redisFlagReadonly, redisFlagFast}, 1, 1, 1) + registerCommand("HStrlen", execHStrlen, readFirstKey, nil, 3, flagReadOnly). + attachCommandExtra([]string{redisFlagReadonly, redisFlagFast}, 1, 1, 1) + registerCommand("HMSet", execHMSet, writeFirstKey, undoHMSet, -4, flagWrite). + attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM, redisFlagFast}, 1, 1, 1) + registerCommand("HMGet", execHMGet, readFirstKey, nil, -3, flagReadOnly). + attachCommandExtra([]string{redisFlagReadonly, redisFlagFast}, 1, 1, 1) + registerCommand("HGet", execHGet, readFirstKey, nil, -3, flagReadOnly). + attachCommandExtra([]string{redisFlagReadonly, redisFlagFast}, 1, 1, 1) + registerCommand("HKeys", execHKeys, readFirstKey, nil, 2, flagReadOnly). + attachCommandExtra([]string{redisFlagReadonly, redisFlagSortForScript}, 1, 1, 1) + registerCommand("HVals", execHVals, readFirstKey, nil, 2, flagReadOnly). + attachCommandExtra([]string{redisFlagReadonly, redisFlagSortForScript}, 1, 1, 1) + registerCommand("HGetAll", execHGetAll, readFirstKey, nil, 2, flagReadOnly). + attachCommandExtra([]string{redisFlagReadonly, redisFlagRandom}, 1, 1, 1) + registerCommand("HIncrBy", execHIncrBy, writeFirstKey, undoHIncr, 4, flagWrite). + attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM, redisFlagFast}, 1, 1, 1) + registerCommand("HIncrByFloat", execHIncrByFloat, writeFirstKey, undoHIncr, 4, flagWrite). + attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM, redisFlagFast}, 1, 1, 1) + registerCommand("HRandField", execHRandField, readFirstKey, nil, -2, flagReadOnly). + attachCommandExtra([]string{redisFlagRandom, redisFlagReadonly}, 1, 1, 1) } diff --git a/database/keys.go b/database/keys.go index 1f028ef..7bd24bc 100644 --- a/database/keys.go +++ b/database/keys.go @@ -410,37 +410,34 @@ func execCopy(mdb *Server, conn redis.Connection, args [][]byte) redis.Reply { } func init() { - RegisterCommand("Del", execDel, writeAllKeys, undoDel, -2, flagWrite) - RegisterCommand("Expire", execExpire, writeFirstKey, undoExpire, 3, flagWrite) - RegisterCommand("ExpireAt", execExpireAt, writeFirstKey, undoExpire, 3, flagWrite) - RegisterCommand("ExpireTime", execExpireTime, readFirstKey, nil, 2, flagReadOnly) - RegisterCommand("PExpire", execPExpire, writeFirstKey, undoExpire, 3, flagWrite) - RegisterCommand("PExpireAt", execPExpireAt, writeFirstKey, undoExpire, 3, flagWrite) - RegisterCommand("PExpireTime", execPExpireTime, readFirstKey, nil, 2, flagReadOnly) - RegisterCommand("TTL", execTTL, readFirstKey, nil, 2, flagReadOnly) - RegisterCommand("PTTL", execPTTL, readFirstKey, nil, 2, flagReadOnly) - RegisterCommand("Persist", execPersist, writeFirstKey, undoExpire, 2, flagWrite) - RegisterCommand("Exists", execExists, readAllKeys, nil, -2, flagReadOnly) - RegisterCommand("Type", execType, readFirstKey, nil, 2, flagReadOnly) - RegisterCommand("Rename", execRename, prepareRename, undoRename, 3, flagReadOnly) - RegisterCommand("RenameNx", execRenameNx, prepareRename, undoRename, 3, flagReadOnly) - RegisterCommand("Keys", execKeys, noPrepare, nil, 2, flagReadOnly) -} - -func init() { - RegisterGodisCommand("Del", -2, []string{Write}, 1, -1, 1, writeAllKeys) - RegisterGodisCommand("Expire", 3, []string{Write, Fast}, 1, 1, 1, writeFirstKey) - RegisterGodisCommand("ExpireAt", 3, []string{Write, Fast}, 1, 1, 1, writeFirstKey) - RegisterGodisCommand("ExpireTime", 2, []string{Write, Fast}, 1, 1, 1, readFirstKey) - RegisterGodisCommand("PExpire", 3, []string{Write, Fast}, 1, 1, 1, writeFirstKey) - RegisterGodisCommand("PExpireAt", 3, []string{Write, Fast}, 1, 1, 1, writeFirstKey) - RegisterGodisCommand("PExpireTime", 2, []string{Write, Fast}, 1, 1, 1, readFirstKey) - RegisterGodisCommand("TTL", 2, []string{Readonly, Random, Fast}, 1, 1, 1, readFirstKey) - RegisterGodisCommand("PTTL", 2, []string{Readonly, Random, Fast}, 1, 1, 1, readFirstKey) - RegisterGodisCommand("Persist", 2, []string{Write, Fast}, 1, 1, 1, writeFirstKey) - RegisterGodisCommand("Exists", -2, []string{Readonly, Fast}, 1, 1, 1, readAllKeys) - RegisterGodisCommand("Type", 2, []string{Readonly, Fast}, 1, 1, 1, readFirstKey) - 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) + registerCommand("Del", execDel, writeAllKeys, undoDel, -2, flagWrite). + attachCommandExtra([]string{redisFlagWrite}, 1, -1, 1) + registerCommand("Expire", execExpire, writeFirstKey, undoExpire, 3, flagWrite). + attachCommandExtra([]string{redisFlagWrite, redisFlagFast}, 1, 1, 1) + registerCommand("ExpireAt", execExpireAt, writeFirstKey, undoExpire, 3, flagWrite). + attachCommandExtra([]string{redisFlagWrite, redisFlagFast}, 1, 1, 1) + registerCommand("ExpireTime", execExpireTime, readFirstKey, nil, 2, flagReadOnly). + attachCommandExtra([]string{redisFlagWrite, redisFlagFast}, 1, 1, 1) + registerCommand("PExpire", execPExpire, writeFirstKey, undoExpire, 3, flagWrite). + attachCommandExtra([]string{redisFlagWrite, redisFlagFast}, 1, 1, 1) + registerCommand("PExpireAt", execPExpireAt, writeFirstKey, undoExpire, 3, flagWrite). + attachCommandExtra([]string{redisFlagWrite, redisFlagFast}, 1, 1, 1) + registerCommand("PExpireTime", execPExpireTime, readFirstKey, nil, 2, flagReadOnly). + attachCommandExtra([]string{redisFlagWrite, redisFlagFast}, 1, 1, 1) + registerCommand("TTL", execTTL, readFirstKey, nil, 2, flagReadOnly). + attachCommandExtra([]string{redisFlagReadonly, redisFlagRandom, redisFlagFast}, 1, 1, 1) + registerCommand("PTTL", execPTTL, readFirstKey, nil, 2, flagReadOnly). + attachCommandExtra([]string{redisFlagReadonly, redisFlagRandom, redisFlagFast}, 1, 1, 1) + registerCommand("Persist", execPersist, writeFirstKey, undoExpire, 2, flagWrite). + attachCommandExtra([]string{redisFlagWrite, redisFlagFast}, 1, 1, 1) + registerCommand("Exists", execExists, readAllKeys, nil, -2, flagReadOnly). + attachCommandExtra([]string{redisFlagReadonly, redisFlagFast}, 1, 1, 1) + registerCommand("Type", execType, readFirstKey, nil, 2, flagReadOnly). + attachCommandExtra([]string{redisFlagReadonly, redisFlagFast}, 1, 1, 1) + registerCommand("Rename", execRename, prepareRename, undoRename, 3, flagReadOnly). + attachCommandExtra([]string{redisFlagWrite}, 1, 1, 1) + registerCommand("RenameNx", execRenameNx, prepareRename, undoRename, 3, flagReadOnly). + attachCommandExtra([]string{redisFlagWrite, redisFlagFast}, 1, 1, 1) + registerCommand("Keys", execKeys, noPrepare, nil, 2, flagReadOnly). + attachCommandExtra([]string{redisFlagReadonly, redisFlagSortForScript}, 1, 1, 1) } diff --git a/database/list.go b/database/list.go index 8d0ada8..5d4891a 100644 --- a/database/list.go +++ b/database/list.go @@ -511,31 +511,28 @@ func execRPushX(db *DB, args [][]byte) redis.Reply { } func init() { - RegisterCommand("LPush", execLPush, writeFirstKey, undoLPush, -3, flagWrite) - RegisterCommand("LPushX", execLPushX, writeFirstKey, undoLPush, -3, flagWrite) - RegisterCommand("RPush", execRPush, writeFirstKey, undoRPush, -3, flagWrite) - RegisterCommand("RPushX", execRPushX, writeFirstKey, undoRPush, -3, flagWrite) - RegisterCommand("LPop", execLPop, writeFirstKey, undoLPop, 2, flagWrite) - RegisterCommand("RPop", execRPop, writeFirstKey, undoRPop, 2, flagWrite) - RegisterCommand("RPopLPush", execRPopLPush, prepareRPopLPush, undoRPopLPush, 3, flagWrite) - RegisterCommand("LRem", execLRem, writeFirstKey, rollbackFirstKey, 4, flagWrite) - RegisterCommand("LLen", execLLen, readFirstKey, nil, 2, flagReadOnly) - RegisterCommand("LIndex", execLIndex, readFirstKey, nil, 3, flagReadOnly) - RegisterCommand("LSet", execLSet, writeFirstKey, undoLSet, 4, flagWrite) - RegisterCommand("LRange", execLRange, readFirstKey, nil, 4, flagReadOnly) -} - -func init() { - RegisterGodisCommand("LPush", -3, []string{Write, Denyoom, Fast}, 1, 1, 1, writeFirstKey) - RegisterGodisCommand("LPushX", -3, []string{Write, Denyoom, Fast}, 1, 1, 1, writeFirstKey) - RegisterGodisCommand("RPush", -3, []string{Write, Denyoom, Fast}, 1, 1, 1, writeFirstKey) - RegisterGodisCommand("RPushX", -3, []string{Write, Denyoom, Fast}, 1, 1, 1, writeFirstKey) - RegisterGodisCommand("LPop", 2, []string{Write, Fast}, 1, 1, 1, writeFirstKey) - RegisterGodisCommand("RPop", 2, []string{Write, Fast}, 1, 1, 1, writeFirstKey) - RegisterGodisCommand("RPopLPush", 3, []string{Write, Denyoom}, 1, 1, 1, prepareRPopLPush) - RegisterGodisCommand("LRem", 4, []string{Write}, 1, 1, 1, writeFirstKey) - RegisterGodisCommand("LLen", 2, []string{Readonly, Fast}, 1, 1, 1, readFirstKey) - 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) + registerCommand("LPush", execLPush, writeFirstKey, undoLPush, -3, flagWrite). + attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM, redisFlagFast}, 1, 1, 1) + registerCommand("LPushX", execLPushX, writeFirstKey, undoLPush, -3, flagWrite). + attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM, redisFlagFast}, 1, 1, 1) + registerCommand("RPush", execRPush, writeFirstKey, undoRPush, -3, flagWrite). + attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM, redisFlagFast}, 1, 1, 1) + registerCommand("RPushX", execRPushX, writeFirstKey, undoRPush, -3, flagWrite). + attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM, redisFlagFast}, 1, 1, 1) + registerCommand("LPop", execLPop, writeFirstKey, undoLPop, 2, flagWrite). + attachCommandExtra([]string{redisFlagWrite, redisFlagFast}, 1, 1, 1) + registerCommand("RPop", execRPop, writeFirstKey, undoRPop, 2, flagWrite). + attachCommandExtra([]string{redisFlagWrite, redisFlagFast}, 1, 1, 1) + registerCommand("RPopLPush", execRPopLPush, prepareRPopLPush, undoRPopLPush, 3, flagWrite). + attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM}, 1, 1, 1) + registerCommand("LRem", execLRem, writeFirstKey, rollbackFirstKey, 4, flagWrite). + attachCommandExtra([]string{redisFlagWrite}, 1, 1, 1) + registerCommand("LLen", execLLen, readFirstKey, nil, 2, flagReadOnly). + attachCommandExtra([]string{redisFlagReadonly, redisFlagFast}, 1, 1, 1) + registerCommand("LIndex", execLIndex, readFirstKey, nil, 3, flagReadOnly). + attachCommandExtra([]string{redisFlagReadonly}, 1, 1, 1) + registerCommand("LSet", execLSet, writeFirstKey, undoLSet, 4, flagWrite). + attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM}, 1, 1, 1) + registerCommand("LRange", execLRange, readFirstKey, nil, 4, flagReadOnly). + attachCommandExtra([]string{redisFlagReadonly}, 1, 1, 1) } diff --git a/database/router.go b/database/router.go index 9274a72..96e2aa4 100644 --- a/database/router.go +++ b/database/router.go @@ -1,36 +1,67 @@ package database import ( + "github.com/hdt3213/godis/interface/redis" + "github.com/hdt3213/godis/redis/protocol" "strings" ) var cmdTable = make(map[string]*command) type command struct { + name string executor ExecFunc - prepare PreFunc // return related keys command - undo UndoFunc - arity int // allow number of args, arity < 0 means len(args) >= -arity - flags int + // prepare returns related keys command + prepare PreFunc + // undo generates undo-log before command actually executed, in case the command needs to be rolled back + 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 ( - flagWrite = 0 - flagReadOnly = 1 + flagReadOnly = 1 << iota + flagSpecial // command invoked in Exec ) -// RegisterCommand registers a new command -// arity means allowed number of cmdArgs, arity < 0 means len(args) >= -arity. -// 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) { +// registerCommand registers a normal command, which only read or modify a limited number of keys +func registerCommand(name string, executor ExecFunc, prepare PreFunc, rollback UndoFunc, arity int, flags int) *command { name = strings.ToLower(name) - cmdTable[name] = &command{ + cmd := &command{ + name: name, executor: executor, prepare: prepare, undo: rollback, arity: arity, 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 { @@ -41,3 +72,32 @@ func isReadOnlyCommand(name string) bool { } 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, + } +} diff --git a/database/server.go b/database/server.go index 61a0512..8962c30 100644 --- a/database/server.go +++ b/database/server.go @@ -94,13 +94,13 @@ func (server *Server) Exec(c redis.Connection, cmdLine [][]byte) (result redis.R if cmdName == "auth" { return Auth(c, cmdLine[1:]) } + if !isAuthenticated(c) { + return protocol.MakeErrReply("NOAUTH Authentication required") + } // info if cmdName == "info" { return Info(c, cmdLine) } - if !isAuthenticated(c) { - return protocol.MakeErrReply("NOAUTH Authentication required") - } if cmdName == "slaveof" { if c != nil && c.InMultiState() { return protocol.MakeErrReply("cannot use slave of database within multi") diff --git a/database/set.go b/database/set.go index 48845b5..41282fb 100644 --- a/database/set.go +++ b/database/set.go @@ -479,33 +479,30 @@ func execSRandMember(db *DB, args [][]byte) redis.Reply { } func init() { - RegisterCommand("SAdd", execSAdd, writeFirstKey, undoSetChange, -3, flagWrite) - RegisterCommand("SIsMember", execSIsMember, readFirstKey, nil, 3, flagReadOnly) - RegisterCommand("SRem", execSRem, writeFirstKey, undoSetChange, -3, flagWrite) - RegisterCommand("SPop", execSPop, writeFirstKey, undoSetChange, -2, flagWrite) - RegisterCommand("SCard", execSCard, readFirstKey, nil, 2, flagReadOnly) - RegisterCommand("SMembers", execSMembers, readFirstKey, nil, 2, flagReadOnly) - RegisterCommand("SInter", execSInter, prepareSetCalculate, nil, -2, flagReadOnly) - RegisterCommand("SInterStore", execSInterStore, prepareSetCalculateStore, rollbackFirstKey, -3, flagWrite) - RegisterCommand("SUnion", execSUnion, prepareSetCalculate, nil, -2, flagReadOnly) - RegisterCommand("SUnionStore", execSUnionStore, prepareSetCalculateStore, rollbackFirstKey, -3, flagWrite) - RegisterCommand("SDiff", execSDiff, prepareSetCalculate, nil, -2, flagReadOnly) - RegisterCommand("SDiffStore", execSDiffStore, prepareSetCalculateStore, rollbackFirstKey, -3, flagWrite) - RegisterCommand("SRandMember", execSRandMember, readFirstKey, nil, -2, flagReadOnly) -} - -func init() { - RegisterGodisCommand("SAdd", -3, []string{Write, Denyoom, Fast}, 1, 1, 1, writeFirstKey) - RegisterGodisCommand("SIsMember", 3, []string{Readonly, Fast}, 1, 1, 1, readFirstKey) - RegisterGodisCommand("SRem", -3, []string{Write, Fast}, 1, 1, 1, writeFirstKey) - RegisterGodisCommand("SPop", -2, []string{Write, Random, Fast}, 1, 1, 1, writeFirstKey) - RegisterGodisCommand("SCard", 2, []string{Readonly, Fast}, 1, 1, 1, readFirstKey) - RegisterGodisCommand("SMembers", 2, []string{Readonly, SortForScript}, 1, 1, 1, readFirstKey) - RegisterGodisCommand("SInter", -2, []string{Readonly, SortForScript}, 1, -1, 1, prepareSetCalculate) - RegisterGodisCommand("SInterStore", -3, []string{Write, Denyoom}, 1, -1, 1, prepareSetCalculateStore) - RegisterGodisCommand("SUnion", -2, []string{Readonly, SortForScript}, 1, -1, 1, prepareSetCalculate) - RegisterGodisCommand("SUnionStore", -3, []string{Write, Denyoom}, 1, -1, 1, prepareSetCalculateStore) - 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) + registerCommand("SAdd", execSAdd, writeFirstKey, undoSetChange, -3, flagWrite). + attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM, redisFlagFast}, 1, 1, 1) + registerCommand("SIsMember", execSIsMember, readFirstKey, nil, 3, flagReadOnly). + attachCommandExtra([]string{redisFlagReadonly, redisFlagFast}, 1, 1, 1) + registerCommand("SRem", execSRem, writeFirstKey, undoSetChange, -3, flagWrite). + attachCommandExtra([]string{redisFlagWrite, redisFlagFast}, 1, 1, 1) + registerCommand("SPop", execSPop, writeFirstKey, undoSetChange, -2, flagWrite). + attachCommandExtra([]string{redisFlagWrite, redisFlagRandom, redisFlagFast}, 1, 1, 1) + registerCommand("SCard", execSCard, readFirstKey, nil, 2, flagReadOnly). + attachCommandExtra([]string{redisFlagReadonly, redisFlagFast}, 1, 1, 1) + registerCommand("SMembers", execSMembers, readFirstKey, nil, 2, flagReadOnly). + attachCommandExtra([]string{redisFlagReadonly, redisFlagSortForScript}, 1, 1, 1) + registerCommand("SInter", execSInter, prepareSetCalculate, nil, -2, flagReadOnly). + attachCommandExtra([]string{redisFlagReadonly, redisFlagSortForScript}, 1, -1, 1) + registerCommand("SInterStore", execSInterStore, prepareSetCalculateStore, rollbackFirstKey, -3, flagWrite). + attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM}, 1, -1, 1) + registerCommand("SUnion", execSUnion, prepareSetCalculate, nil, -2, flagReadOnly). + attachCommandExtra([]string{redisFlagReadonly, redisFlagSortForScript}, 1, -1, 1) + registerCommand("SUnionStore", execSUnionStore, prepareSetCalculateStore, rollbackFirstKey, -3, flagWrite). + attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM}, 1, -1, 1) + registerCommand("SDiff", execSDiff, prepareSetCalculate, nil, -2, flagReadOnly). + attachCommandExtra([]string{redisFlagReadonly, redisFlagSortForScript}, 1, 1, 1) + registerCommand("SDiffStore", execSDiffStore, prepareSetCalculateStore, rollbackFirstKey, -3, flagWrite). + attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM}, 1, 1, 1) + registerCommand("SRandMember", execSRandMember, readFirstKey, nil, -2, flagReadOnly). + attachCommandExtra([]string{redisFlagReadonly, redisFlagRandom}, 1, 1, 1) } diff --git a/database/sortedset.go b/database/sortedset.go index 7e51644..cb7c427 100644 --- a/database/sortedset.go +++ b/database/sortedset.go @@ -622,37 +622,34 @@ func undoZIncr(db *DB, args [][]byte) []CmdLine { } func init() { - RegisterCommand("ZAdd", execZAdd, writeFirstKey, undoZAdd, -4, flagWrite) - RegisterCommand("ZScore", execZScore, readFirstKey, nil, 3, flagReadOnly) - RegisterCommand("ZIncrBy", execZIncrBy, writeFirstKey, undoZIncr, 4, flagWrite) - RegisterCommand("ZRank", execZRank, readFirstKey, nil, 3, flagReadOnly) - RegisterCommand("ZCount", execZCount, readFirstKey, nil, 4, flagReadOnly) - RegisterCommand("ZRevRank", execZRevRank, readFirstKey, nil, 3, flagReadOnly) - RegisterCommand("ZCard", execZCard, readFirstKey, nil, 2, flagReadOnly) - RegisterCommand("ZRange", execZRange, readFirstKey, nil, -4, flagReadOnly) - RegisterCommand("ZRangeByScore", execZRangeByScore, readFirstKey, nil, -4, flagReadOnly) - RegisterCommand("ZRevRange", execZRevRange, readFirstKey, nil, -4, flagReadOnly) - RegisterCommand("ZRevRangeByScore", execZRevRangeByScore, readFirstKey, nil, -4, flagReadOnly) - RegisterCommand("ZPopMin", execZPopMin, writeFirstKey, rollbackFirstKey, -2, flagWrite) - RegisterCommand("ZRem", execZRem, writeFirstKey, undoZRem, -3, flagWrite) - RegisterCommand("ZRemRangeByScore", execZRemRangeByScore, writeFirstKey, rollbackFirstKey, 4, flagWrite) - RegisterCommand("ZRemRangeByRank", execZRemRangeByRank, writeFirstKey, rollbackFirstKey, 4, flagWrite) -} - -func init() { - RegisterGodisCommand("ZAdd", -4, []string{Write, Denyoom, Fast}, 1, 1, 1, writeFirstKey) - RegisterGodisCommand("ZScore", 3, []string{Readonly, Fast}, 1, 1, 1, readFirstKey) - RegisterGodisCommand("ZIncrBy", 4, []string{Write, Denyoom, Fast}, 1, 1, 1, writeFirstKey) - RegisterGodisCommand("ZRank", 3, []string{Readonly, Fast}, 1, 1, 1, readFirstKey) - RegisterGodisCommand("ZCount", 4, []string{Readonly, Fast}, 1, 1, 1, readFirstKey) - RegisterGodisCommand("ZRevRank", 3, []string{Readonly, Fast}, 1, 1, 1, readFirstKey) - RegisterGodisCommand("ZCard", 2, []string{Readonly, Fast}, 1, 1, 1, readFirstKey) - RegisterGodisCommand("ZRange", -4, []string{Readonly}, 1, 1, 1, readFirstKey) - RegisterGodisCommand("ZRangeByScore", -4, []string{Readonly}, 1, 1, 1, readFirstKey) - RegisterGodisCommand("ZRevRange", -4, []string{Readonly}, 1, 1, 1, readFirstKey) - RegisterGodisCommand("ZRevRangeByScore", -4, []string{Readonly}, 1, 1, 1, readFirstKey) - RegisterGodisCommand("ZPopMin", -2, []string{Write, Fast}, 1, 1, 1, writeFirstKey) - 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) + registerCommand("ZAdd", execZAdd, writeFirstKey, undoZAdd, -4, flagWrite). + attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM, redisFlagFast}, 1, 1, 1) + registerCommand("ZScore", execZScore, readFirstKey, nil, 3, flagReadOnly). + attachCommandExtra([]string{redisFlagReadonly, redisFlagFast}, 1, 1, 1) + registerCommand("ZIncrBy", execZIncrBy, writeFirstKey, undoZIncr, 4, flagWrite). + attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM, redisFlagFast}, 1, 1, 1) + registerCommand("ZRank", execZRank, readFirstKey, nil, 3, flagReadOnly). + attachCommandExtra([]string{redisFlagReadonly, redisFlagFast}, 1, 1, 1) + registerCommand("ZCount", execZCount, readFirstKey, nil, 4, flagReadOnly). + attachCommandExtra([]string{redisFlagReadonly, redisFlagFast}, 1, 1, 1) + registerCommand("ZRevRank", execZRevRank, readFirstKey, nil, 3, flagReadOnly). + attachCommandExtra([]string{redisFlagReadonly, redisFlagFast}, 1, 1, 1) + registerCommand("ZCard", execZCard, readFirstKey, nil, 2, flagReadOnly). + attachCommandExtra([]string{redisFlagReadonly, redisFlagFast}, 1, 1, 1) + registerCommand("ZRange", execZRange, readFirstKey, nil, -4, flagReadOnly). + attachCommandExtra([]string{redisFlagReadonly}, 1, 1, 1) + registerCommand("ZRangeByScore", execZRangeByScore, readFirstKey, nil, -4, flagReadOnly). + attachCommandExtra([]string{redisFlagReadonly}, 1, 1, 1) + registerCommand("ZRevRange", execZRevRange, readFirstKey, nil, -4, flagReadOnly). + attachCommandExtra([]string{redisFlagReadonly}, 1, 1, 1) + registerCommand("ZRevRangeByScore", execZRevRangeByScore, readFirstKey, nil, -4, flagReadOnly). + attachCommandExtra([]string{redisFlagReadonly}, 1, 1, 1) + registerCommand("ZPopMin", execZPopMin, writeFirstKey, rollbackFirstKey, -2, flagWrite). + attachCommandExtra([]string{redisFlagWrite, redisFlagFast}, 1, 1, 1) + registerCommand("ZRem", execZRem, writeFirstKey, undoZRem, -3, flagWrite). + attachCommandExtra([]string{redisFlagWrite, redisFlagFast}, 1, 1, 1) + registerCommand("ZRemRangeByScore", execZRemRangeByScore, writeFirstKey, rollbackFirstKey, 4, flagWrite). + attachCommandExtra([]string{redisFlagWrite}, 1, 1, 1) + registerCommand("ZRemRangeByRank", execZRemRangeByRank, writeFirstKey, rollbackFirstKey, 4, flagWrite). + attachCommandExtra([]string{redisFlagWrite}, 1, 1, 1) } diff --git a/database/string.go b/database/string.go index e65b46a..9fb0df7 100644 --- a/database/string.go +++ b/database/string.go @@ -837,59 +837,53 @@ func getRandomKey(db *DB, args [][]byte) redis.Reply { } func init() { - RegisterCommand("Set", execSet, writeFirstKey, rollbackFirstKey, -3, flagWrite) - RegisterCommand("SetNx", execSetNX, writeFirstKey, rollbackFirstKey, 3, flagWrite) - RegisterCommand("SetEX", execSetEX, writeFirstKey, rollbackFirstKey, 4, flagWrite) - RegisterCommand("PSetEX", execPSetEX, writeFirstKey, rollbackFirstKey, 4, flagWrite) - RegisterCommand("MSet", execMSet, prepareMSet, undoMSet, -3, flagWrite) - RegisterCommand("MGet", execMGet, prepareMGet, nil, -2, flagReadOnly) - RegisterCommand("MSetNX", execMSetNX, prepareMSet, undoMSet, -3, flagWrite) - RegisterCommand("Get", execGet, readFirstKey, nil, 2, flagReadOnly) - RegisterCommand("GetEX", execGetEX, writeFirstKey, rollbackFirstKey, -2, flagReadOnly) - RegisterCommand("GetSet", execGetSet, writeFirstKey, rollbackFirstKey, 3, flagWrite) - RegisterCommand("GetDel", execGetDel, writeFirstKey, rollbackFirstKey, 2, flagWrite) - RegisterCommand("Incr", execIncr, writeFirstKey, rollbackFirstKey, 2, flagWrite) - RegisterCommand("IncrBy", execIncrBy, writeFirstKey, rollbackFirstKey, 3, flagWrite) - RegisterCommand("IncrByFloat", execIncrByFloat, writeFirstKey, rollbackFirstKey, 3, flagWrite) - RegisterCommand("Decr", execDecr, writeFirstKey, rollbackFirstKey, 2, flagWrite) - RegisterCommand("DecrBy", execDecrBy, writeFirstKey, rollbackFirstKey, 3, flagWrite) - RegisterCommand("StrLen", execStrLen, readFirstKey, nil, 2, flagReadOnly) - RegisterCommand("Append", execAppend, writeFirstKey, rollbackFirstKey, 3, flagWrite) - RegisterCommand("SetRange", execSetRange, writeFirstKey, rollbackFirstKey, 4, flagWrite) - RegisterCommand("GetRange", execGetRange, readFirstKey, nil, 4, flagReadOnly) - RegisterCommand("SetBit", execSetBit, writeFirstKey, rollbackFirstKey, 4, flagWrite) - RegisterCommand("GetBit", execGetBit, readFirstKey, nil, 3, flagReadOnly) - RegisterCommand("BitCount", execBitCount, readFirstKey, nil, -2, flagReadOnly) - RegisterCommand("BitPos", execBitPos, readFirstKey, nil, -3, flagReadOnly) - RegisterCommand("Randomkey", getRandomKey, readAllKeys, nil, 1, flagReadOnly) - -} - -func init() { - RegisterGodisCommand("Set", -3, []string{Write, Denyoom}, 1, 1, 1, writeFirstKey) - RegisterGodisCommand("SetNx", 3, []string{Write, Denyoom, Fast}, 1, 1, 1, writeFirstKey) - RegisterGodisCommand("SetEX", 4, []string{Write, Denyoom}, 1, 1, 1, writeFirstKey) - RegisterGodisCommand("PSetEX", 4, []string{Write, Denyoom}, 1, 1, 1, writeFirstKey) - RegisterGodisCommand("MSet", -3, []string{Write, Denyoom}, 1, -1, 2, prepareMSet) - RegisterGodisCommand("MGet", -2, []string{Readonly, Fast}, 1, 1, 1, prepareMSet) - RegisterGodisCommand("MSetNX", -3, []string{Write, Denyoom}, 1, 1, 1, prepareMSet) - RegisterGodisCommand("Get", 2, []string{Readonly, Fast}, 1, 1, 1, readFirstKey) - RegisterGodisCommand("GetEX", -2, []string{Readonly, Fast}, 1, 1, 1, writeFirstKey) - RegisterGodisCommand("GetSet", 3, []string{Write, Denyoom}, 1, 1, 1, writeFirstKey) - RegisterGodisCommand("GetDel", 2, []string{Write, Denyoom}, 1, 1, 1, writeFirstKey) - RegisterGodisCommand("Incr", 2, []string{Write, Denyoom, Fast}, 1, 1, 1, writeFirstKey) - RegisterGodisCommand("IncrBy", 3, []string{Write, Denyoom}, 1, 1, 1, writeFirstKey) - RegisterGodisCommand("IncrByFloat", 3, []string{Write, Denyoom}, 1, 1, 1, writeFirstKey) - RegisterGodisCommand("Decr", 2, []string{Write, Denyoom}, 1, 1, 1, writeFirstKey) - RegisterGodisCommand("DecrBy", 3, []string{Write, Denyoom}, 1, 1, 1, writeFirstKey) - RegisterGodisCommand("StrLen", 2, []string{Readonly, Fast}, 1, 1, 1, readFirstKey) - RegisterGodisCommand("Append", 3, []string{Write, Denyoom}, 1, 1, 1, writeFirstKey) - RegisterGodisCommand("SetRange", 4, []string{Write, Denyoom}, 1, 1, 1, writeFirstKey) - RegisterGodisCommand("GetRange", 4, []string{Readonly}, 1, 1, 1, readFirstKey) - 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) - + registerCommand("Set", execSet, writeFirstKey, rollbackFirstKey, -3, flagWrite). + attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM}, 1, 1, 1) + registerCommand("SetNx", execSetNX, writeFirstKey, rollbackFirstKey, 3, flagWrite). + attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM, redisFlagFast}, 1, 1, 1) + registerCommand("SetEX", execSetEX, writeFirstKey, rollbackFirstKey, 4, flagWrite). + attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM}, 1, 1, 1) + registerCommand("PSetEX", execPSetEX, writeFirstKey, rollbackFirstKey, 4, flagWrite). + attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM}, 1, 1, 1) + registerCommand("MSet", execMSet, prepareMSet, undoMSet, -3, flagWrite). + attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM}, 1, -1, 2) + registerCommand("MGet", execMGet, prepareMGet, nil, -2, flagReadOnly). + attachCommandExtra([]string{redisFlagReadonly, redisFlagFast}, 1, 1, 1) + registerCommand("MSetNX", execMSetNX, prepareMSet, undoMSet, -3, flagWrite). + attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM}, 1, 1, 1) + registerCommand("Get", execGet, readFirstKey, nil, 2, flagReadOnly). + attachCommandExtra([]string{redisFlagReadonly, redisFlagFast}, 1, 1, 1) + registerCommand("GetEX", execGetEX, writeFirstKey, rollbackFirstKey, -2, flagReadOnly). + attachCommandExtra([]string{redisFlagReadonly, redisFlagFast}, 1, 1, 1) + registerCommand("GetSet", execGetSet, writeFirstKey, rollbackFirstKey, 3, flagWrite). + attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM}, 1, 1, 1) + registerCommand("GetDel", execGetDel, writeFirstKey, rollbackFirstKey, 2, flagWrite). + attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM}, 1, 1, 1) + registerCommand("Incr", execIncr, writeFirstKey, rollbackFirstKey, 2, flagWrite). + attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM, redisFlagFast}, 1, 1, 1) + 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). + attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM}, 1, 1, 1) + registerCommand("DecrBy", execDecrBy, writeFirstKey, rollbackFirstKey, 3, flagWrite). + attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM}, 1, 1, 1) + registerCommand("StrLen", execStrLen, readFirstKey, nil, 2, flagReadOnly). + attachCommandExtra([]string{redisFlagReadonly, redisFlagFast}, 1, 1, 1) + registerCommand("Append", execAppend, writeFirstKey, rollbackFirstKey, 3, flagWrite). + attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM}, 1, 1, 1) + registerCommand("SetRange", execSetRange, writeFirstKey, rollbackFirstKey, 4, flagWrite). + attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM}, 1, 1, 1) + registerCommand("GetRange", execGetRange, readFirstKey, nil, 4, flagReadOnly). + attachCommandExtra([]string{redisFlagReadonly}, 1, 1, 1) + registerCommand("SetBit", execSetBit, writeFirstKey, rollbackFirstKey, 4, flagWrite). + attachCommandExtra([]string{redisFlagWrite, redisFlagDenyOOM}, 1, 1, 1) + registerCommand("GetBit", execGetBit, readFirstKey, nil, 3, flagReadOnly). + attachCommandExtra([]string{redisFlagReadonly, redisFlagFast}, 1, 1, 1) + registerCommand("BitCount", execBitCount, readFirstKey, nil, -2, flagReadOnly). + attachCommandExtra([]string{redisFlagReadonly}, 1, 1, 1) + registerCommand("BitPos", execBitPos, readFirstKey, nil, -3, flagReadOnly). + attachCommandExtra([]string{redisFlagReadonly}, 1, 1, 1) + registerCommand("Randomkey", getRandomKey, readAllKeys, nil, 1, flagReadOnly). + attachCommandExtra([]string{redisFlagReadonly, redisFlagRandom}, 1, 1, 1) } diff --git a/database/transaction.go b/database/transaction.go index 376de0c..d91a38b 100644 --- a/database/transaction.go +++ b/database/transaction.go @@ -23,7 +23,7 @@ func execGetVersion(db *DB, args [][]byte) redis.Reply { } func init() { - RegisterCommand("GetVer", execGetVersion, readAllKeys, nil, 2, flagReadOnly) + registerCommand("GetVer", execGetVersion, readAllKeys, nil, 2, flagReadOnly) } // invoker should lock watching keys