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 *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 (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 TestBackend(t *testing.T) { l, err := net.Listen("tcp", "127.0.0.1:0") assert.MustNoError(err) defer l.Close() addr := l.Addr().String() reqc := make(chan *Request, 16384) go func() { bc := NewBackendConn(addr, "") defer bc.Close() defer close(reqc) var resp = redis.NewBulkBytes(make([]byte, 4096)) for i := 0; i < cap(reqc); i++ { r := &Request{ Resp: resp, Wait: &sync.WaitGroup{}, } bc.PushBack(r) reqc <- r } }() go func() { c, err := l.Accept() assert.MustNoError(err) defer c.Close() conn := redis.NewConn(c) time.Sleep(time.Millisecond * 300) for i := 0; i < cap(reqc); i++ { _, err := conn.Reader.Decode() assert.MustNoError(err) resp := redis.NewString([]byte(strconv.Itoa(i))) assert.MustNoError(conn.Writer.Encode(resp, true)) } }() var n int for r := range reqc { r.Wait.Wait() assert.Must(string(r.Response.Resp.Value) == strconv.Itoa(n)) n++ } assert.Must(n == cap(reqc)) }
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 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) } }