func IsMultiCmd(cmd *resp.Command) (multiKey bool, numKeys int) { multiKey = true switch cmd.Name() { case "MGET": numKeys = len(cmd.Args) - 1 case "MSET": numKeys = (len(cmd.Args) - 1) / 2 case "DEL": numKeys = len(cmd.Args) - 1 default: multiKey = false } return }
func NewMultiKeyCmd(cmd *resp.Command, numSubCmds int) *MultiKeyCmd { mc := &MultiKeyCmd{ cmd: cmd, numSubCmds: numSubCmds, numPendingSubCmds: numSubCmds, } switch cmd.Name() { case "MGET": mc.cmdType = MGET case "MSET": mc.cmdType = MSET case "DEL": mc.cmdType = DEL default: panic("not multi key command") } mc.subCmdRsps = make([]*PipelineResponse, numSubCmds) return mc }
func (s *Session) handleMultiKeyCmd(cmd *resp.Command, numKeys int) { var subCmd *resp.Command var err error mc := NewMultiKeyCmd(cmd, numKeys) // multi sub cmd share the same seq number seq := s.getNextReqSeq() readOnly := mc.CmdType() == MGET for i := 0; i < numKeys; i++ { switch mc.CmdType() { case MGET: subCmd, err = resp.NewCommand("GET", cmd.Value(i+1)) case MSET: subCmd, err = resp.NewCommand("SET", cmd.Value(2*i+1), cmd.Value((2*i + 2))) case DEL: subCmd, err = resp.NewCommand("DEL", cmd.Value(i+1)) } if err != nil { panic(err) } key := subCmd.Value(1) slot := Key2Slot(key) plReq := &PipelineRequest{ cmd: subCmd, readOnly: readOnly, slot: slot, seq: seq, subSeq: i, backQ: s.backQ, parentCmd: mc, wg: s.reqWg, } s.reqWg.Add(1) s.dispatcher.Schedule(plReq) } }
func CmdFlag(cmd *resp.Command) int { return cmdFlagMap[cmd.Name()] }