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

@@ -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,
}
}