Example #1
0
func processMc(c net.Conn, pool *redis.Pool) {
	defer log.Printf("%v end processMc", c)
	defer c.Close()

	stats.Connect()
	defer stats.Disconnect()

	// process
	br := bufio.NewReader(c)
	bw := bufio.NewWriter(c)

	// take it per need
	conn := pool.Get()
	defer conn.Close()

	redisProxy := proxy.NewRedisProxy(conn)
	proxy := stats.NewStatsProxy(redisProxy)

	for {
		req, err := protocol.ReadRequest(br)
		if perr, ok := err.(protocol.ProtocolError); ok {
			log.Printf("%v ReadRequest protocol err: %v", c, err)
			bw.WriteString("CLIENT_ERROR " + perr.Error() + "\r\n")
			bw.Flush()
			continue
		} else if err != nil {
			log.Printf("%v ReadRequest err: %v", c, err)
			return
		}
		log.Printf("%v Req: %+v\n", c, req)

		switch req.Command {
		case "quit":
			return
		case "version":
			res := protocol.McResponse{Response: "VERSION mrproxy " + version}
			bw.WriteString(res.Protocol())
			bw.Flush()
		default:
			res := proxy.Process(req)
			if !req.Noreply {
				log.Printf("%v Res: %+v\n", c, res)
				bw.WriteString(res.Protocol())
				bw.Flush()
			}
		}
	}
}
Example #2
0
// process a request and generate a response
func (p *RedisProxy) Process(req *protocol.McRequest) protocol.McResponse {

	switch req.Command {
	case "get":
		res := protocol.McResponse{}
		for i := range req.Keys {

			r, err := redis.Values(p.conn.Do("MGET", req.Keys[i], req.Keys[i]+"_mcflags"))
			if err != nil {
				// hmm, barf errors, or just ignore?
				return serverError(err)
			}
			if r[0] != nil {
				data, err := redis.Bytes(r[0], nil)
				if err != nil {
					return serverErrorText(err, "data")
				}
				flags := "0"
				if r[1] != nil {
					flags, err = redis.String(r[1], nil)
					if err != nil {
						return serverErrorText(err, "flags")
					}
				}
				// todo, both can return error
				res.Values = append(res.Values, protocol.McValue{req.Keys[i], flags, data})
			}
		}
		res.Response = "END"
		return res

	case "set":
		r, err := redis.String(p.conn.Do("MSET", req.Key, req.Data, req.Key+"_mcflags", req.Flags))
		if err != nil || r != "OK" {
			return serverError(err)
		}

		if req.Exptime != 0 {
			_, err = p.conn.Do("EXPIREAT", req.Key, req.Exptime)
			if err != nil {
				return serverError(err)
			}
		}

		return protocol.McResponse{Response: "STORED"}

	case "delete":
		r, err := redis.Int(p.conn.Do("DEL", toInterface(req.Keys)...))
		if err != nil {
			return serverError(err)
		}
		if r > 0 {
			return protocol.McResponse{Response: "DELETED"}
		}
		return protocol.McResponse{Response: "NOT_FOUND"}

		// todo "touch"...
	}

	return protocol.McResponse{Response: "ERROR"}

}