func (bc *BackendConn) verifyAuth(c *redis.Conn) error { if bc.auth == "" { return nil } resp := redis.NewArray([]*redis.Resp{ redis.NewBulkBytes([]byte("AUTH")), redis.NewBulkBytes([]byte(bc.auth)), }) if err := c.Writer.Encode(resp, true); err != nil { return err } resp, err := c.Reader.Decode() if err != nil { return err } if resp == nil { return errors.New(fmt.Sprintf("error resp: nil response")) } if resp.IsError() { return errors.New(fmt.Sprintf("error resp: %s", resp.Value)) } if resp.IsString() { return nil } else { return errors.New(fmt.Sprintf("error resp: should be string, but got %s", resp.Type)) } }
func (s *Session) handleRequestMGet(r *Request, d Dispatcher) (*Request, error) { nkeys := len(r.Resp.Array) - 1 if nkeys <= 1 { return r, d.Dispatch(r) } var sub = make([]*Request, nkeys) for i := 0; i < len(sub); i++ { sub[i] = &Request{ OpStr: r.OpStr, Start: r.Start, Resp: redis.NewArray([]*redis.Resp{ r.Resp.Array[0], r.Resp.Array[i+1], }), Wait: r.Wait, Failed: r.Failed, } if err := d.Dispatch(sub[i]); err != nil { return nil, err } } r.Coalesce = func() error { var array = make([]*redis.Resp, len(sub)) for i, x := range sub { if err := x.Response.Err; err != nil { return err } resp := x.Response.Resp if resp == nil { return ErrRespIsRequired } if !resp.IsArray() || len(resp.Array) != 1 { return errors.New(fmt.Sprintf("bad mget resp: %s array.len = %d", resp.Type, len(resp.Array))) } array[i] = resp.Array[0] } r.Response.Resp = redis.NewArray(array) return nil } return r, nil }
func (bc *BackendConn) KeepAlive() bool { if len(bc.input) != 0 { return false } r := &Request{ Resp: redis.NewArray([]*redis.Resp{ redis.NewBulkBytes([]byte("PING")), }), } select { case bc.input <- r: return true default: return false } }
func (s *Session) handleRequestMSet(r *Request, d Dispatcher) (*Request, error) { nblks := len(r.Resp.Array) - 1 if nblks <= 2 { return r, d.Dispatch(r) } if nblks%2 != 0 { r.Response.Resp = redis.NewError([]byte("ERR wrong number of arguments for 'MSET' command")) return r, nil } var sub = make([]*Request, nblks/2) for i := 0; i < len(sub); i++ { sub[i] = &Request{ OpStr: r.OpStr, Start: r.Start, Resp: redis.NewArray([]*redis.Resp{ r.Resp.Array[0], r.Resp.Array[i*2+1], r.Resp.Array[i*2+2], }), Wait: r.Wait, Failed: r.Failed, } if err := d.Dispatch(sub[i]); err != nil { return nil, err } } r.Coalesce = func() error { for _, x := range sub { if err := x.Response.Err; err != nil { return err } resp := x.Response.Resp if resp == nil { return ErrRespIsRequired } if !resp.IsString() { return errors.New(fmt.Sprintf("bad mset resp: %s value.len = %d", resp.Type, len(resp.Value))) } r.Response.Resp = resp } return nil } return r, nil }
func TestGetOpStr(t *testing.T) { var m = map[string]string{ "get": "GET", "aBc": "ABC", "おはよ": "おはよ", "ni hao!": "NI HAO!", "": "", } for k, v := range m { resp := redis.NewArray([]*redis.Resp{redis.NewBulkBytes([]byte(k))}) s, err := getOpStr(resp) if v != "" { assert.MustNoError(err) assert.Must(s == v) } else { assert.Must(err != nil) } } }
func (s *Session) handleRequestMDel(r *Request, d Dispatcher) (*Request, error) { nkeys := len(r.Resp.Array) - 1 if nkeys <= 1 { return r, d.Dispatch(r) } var sub = make([]*Request, nkeys) for i := 0; i < len(sub); i++ { sub[i] = &Request{ OpStr: r.OpStr, Start: r.Start, Resp: redis.NewArray([]*redis.Resp{ r.Resp.Array[0], r.Resp.Array[i+1], }), Wait: r.Wait, Failed: r.Failed, } if err := d.Dispatch(sub[i]); err != nil { return nil, err } } r.Coalesce = func() error { var n int for _, x := range sub { if err := x.Response.Err; err != nil { return err } resp := x.Response.Resp if resp == nil { return ErrRespIsRequired } if !resp.IsInt() || len(resp.Value) != 1 { return errors.New(fmt.Sprintf("bad mdel resp: %s value.len = %d", resp.Type, len(resp.Value))) } if resp.Value[0] != '0' { n++ } } r.Response.Resp = redis.NewInt([]byte(strconv.Itoa(n))) return nil } return r, nil }
func (s *Slot) slotsmgrt(r *Request, key []byte) error { if len(key) == 0 || s.migrate.bc == nil { return nil } m := &Request{ Resp: redis.NewArray([]*redis.Resp{ redis.NewBulkBytes([]byte("SLOTSMGRTTAGONE")), redis.NewBulkBytes(s.backend.host), redis.NewBulkBytes(s.backend.port), redis.NewBulkBytes([]byte("3000")), redis.NewBulkBytes(key), }), Wait: &sync.WaitGroup{}, } s.migrate.bc.PushBack(m) m.Wait.Wait() resp, err := m.Response.Resp, m.Response.Err if err != nil { return err } if resp == nil { return ErrRespIsRequired } if resp.IsError() { return errors.New(fmt.Sprintf("error resp: %s", resp.Value)) } if resp.IsInt() { log.Debugf("slot-%04d migrate from %s to %s: key = %s, resp = %s", s.id, s.migrate.from, s.backend.addr, key, resp.Value) return nil } else { return errors.New(fmt.Sprintf("error resp: should be integer, but got %s", resp.Type)) } }
func TestGetOpStrCmd(t *testing.T) { var m = map[string]string{ "del": "DEL", "dump": "DUMP", "exists": "EXISTS", "expire": "EXPIRE", "expireat": "EXPIREAT", "persist": "PERSIST", "pexpire": "PEXPIRE", "pexpireat": "PEXPIREAT", "pttl": "PTTL", "restore": "RESTORE", "sort": "SORT", "ttl": "TTL", "type": "TYPE", "append": "APPEND", "bitcount": "BITCOUNT", "decr": "DECR", "decrby": "DECRBY", "get": "GET", "getbit": "GETBIT", "getrange": "GETRANGE", "getset": "GETSET", "incr": "INCR", "incrby": "INCRBY", "incrbyfloat": "INCRBYFLOAT", "mget": "MGET", "mset": "MSET", "psetex": "PSETEX", "set": "SET", "setbit": "SETBIT", "setex": "SETEX", "setnx": "SETNX", "setrange": "SETRANGE", "strlen": "STRLEN", "hdel": "HDEL", "hexists": "HEXISTS", "hget": "HGET", "hgetall": "HGETALL", "hincrby": "HINCRBY", "hincrbyfloat": "HINCRBYFLOAT", "hkeys": "HKEYS", "hlen": "HLEN", "hmget": "HMGET", "hmset": "HMSET", "hset": "HSET", "hsetnx": "HSETNX", "hvals": "HVALS", "hscan": "HSCAN", "lindex": "LINDEX", "linsert": "LINSERT", "llen": "LLEN", "lpop": "LPOP", "lpush": "LPUSH", "lpushx": "LPUSHX", "lrange": "LRANGE", "lrem": "LREM", "lset": "LSET", "ltrim": "LTRIM", "rpop": "RPOP", "rpoplpush": "RPOPLPUSH", "rpush": "RPUSH", "rpushx": "RPUSHX", "sadd": "SADD", "scard": "SCARD", "sdiff": "SDIFF", "sdiffstore": "SDIFFSTORE", "sinter": "SINTER", "sinterstore": "SINTERSTORE", "sismember": "SISMEMBER", "smembers": "SMEMBERS", "smove": "SMOVE", "spop": "SPOP", "srandmember": "SRANDMEMBER", "srem": "SREM", "sunion": "SUNION", "sunionstore": "SUNIONSTORE", "sscan": "SSCAN", "zadd": "ZADD", "zcard": "ZCARD", "zcount": "ZCOUNT", "zincrby": "ZINCRBY", "zinterstore": "ZINTERSTORE", "zlexcount": "ZLEXCOUNT", "zrange": "ZRANGE", "zrangebylex": "ZRANGEBYLEX", "zrangebyscore": "ZRANGEBYSCORE", "zrank": "ZRANK", "zrem": "ZREM", "zremrangebylex": "ZREMRANGEBYLEX", "zremrangebyrank": "ZREMRANGEBYRANK", "zremrangebyscore": "ZREMRANGEBYSCORE", "zrevrange": "ZREVRANGE", "zrevrangebyscore": "ZREVRANGEBYSCORE", "zrevrank": "ZREVRANK", "zscore": "ZSCORE", "zunionstore": "ZUNIONSTORE", "zscan": "ZSCAN", "pfadd": "PFADD", "pfcount": "PFCOUNT", "pfmerge": "PFMERGE", "eval": "EVAL", "evalsha": "EVALSHA", } for k, v := range m { resp := redis.NewArray([]*redis.Resp{redis.NewBulkBytes([]byte(k))}) s, err := getOpStr(resp) assert.MustNoError(err) assert.Must(s == v) } }