/* * 对后端返回的ASK,重新向正确的后端发送 * r : 已经返回ASK的请求 */ func (s *Session) handleAskRequest(r *Request) (*Request, error) { // reset response r.Response.Resp, r.Response.Err = nil, nil usnow := microseconds() s.LastOpUnix = usnow / 1e6 s.Ops++ // get hash key of the request hkey := getHashKey(r.Resp, r.OpStr) log.Infof("ASK: use key: %s to choose backend", string(hkey)) // create a asking request to backend nr := &Request{ OpStr: "ASKING", Start: usnow, Resp: redis.NewString([]byte("ASKING")), Wait: &sync.WaitGroup{}, Failed: &s.failed, } nr, err := s.handleRequestAsking(nr, hkey) log.Infof("ASK: after dispatch asking request, waiting. error=%s", err) if err != nil { return r, err } else { s.GetTasks() <- nr } // resend the r to backend err = s.GetDispather().Dispatch(r) if err == nil { s.GetTasks() <- r } return r, err }
func (s *Session) handlePing(r *Request) (*Request, error) { if len(r.Resp.Array) != 1 { r.Response.Resp = redis.NewError([]byte("ERR wrong number of arguments for 'PING' command")) return r, nil } r.Response.Resp = redis.NewString([]byte("PONG")) return r, nil }
func (s *Session) handleSelect(r *Request) (*Request, error) { if len(r.Resp.Array) != 2 { r.Response.Resp = redis.NewError([]byte("ERR wrong number of arguments for 'SELECT' command")) return r, nil } if db, err := strconv.Atoi(string(r.Resp.Array[1].Value)); err != nil { r.Response.Resp = redis.NewError([]byte("ERR invalid DB index")) return r, nil } else if db != 0 { r.Response.Resp = redis.NewError([]byte("ERR invalid DB index, only accept DB 0")) return r, nil } else { r.Response.Resp = redis.NewString([]byte("OK")) return r, nil } }
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 (s *Session) handleAuth(r *Request) (*Request, error) { if len(r.Resp.Array) != 2 { r.Response.Resp = redis.NewError([]byte("ERR wrong number of arguments for 'AUTH' command")) return r, nil } if s.auth == "" { r.Response.Resp = redis.NewError([]byte("ERR Client sent AUTH, but no password is set")) return r, nil } if s.auth != string(r.Resp.Array[1].Value) { s.authorized = false r.Response.Resp = redis.NewError([]byte("ERR invalid password")) return r, nil } else { s.authorized = true r.Response.Resp = redis.NewString([]byte("OK")) return r, nil } }
func (s *Session) handleQuit(r *Request) (*Request, error) { s.quit = true r.Response.Resp = redis.NewString([]byte("OK")) return r, nil }