Beispiel #1
0
func handleSpecCommand(cmd string, keys [][]byte, timeout int) ([]byte, bool, bool, error) {
	var b []byte
	shouldClose := false
	switch cmd {
	case "PING":
		b = []byte("+PONG\r\n")
	case "QUIT":
		b = OK_BYTES
		shouldClose = true
	case "SELECT":
		b = OK_BYTES
	case "ECHO":
		if len(keys) > 0 {
			var err error
			b, err = respcoding.Marshal(string(keys[0]))
			if err != nil {
				return nil, true, false, errors.Trace(err)
			}
		} else {
			return nil, true, false, nil
		}
	}

	if len(b) > 0 {
		return b, shouldClose, true, nil
	}

	return b, shouldClose, false, nil
}
Beispiel #2
0
func (oper *MultiOperator) mgetResults(mop *MulOp) ([]byte, error) {
	slotmap := getSlotMap(mop.keys)
	results := make([]interface{}, len(mop.keys))
	conn := oper.pool.Get()
	defer conn.Close()
	for _, vec := range slotmap {
		req := make([]interface{}, 0, len(vec))
		for _, p := range vec {
			req = append(req, p.key)
		}

		replys, err := redis.Values(conn.Do("mget", req...))
		if err != nil {
			return nil, errors.Trace(err)
		}

		for i, reply := range replys {
			if reply != nil {
				results[vec[i].pos] = reply
			} else {
				results[vec[i].pos] = nil
			}
		}
	}

	b, err := respcoding.Marshal(results)
	return b, errors.Trace(err)
}
Beispiel #3
0
func (oper *MultiOperator) delResults(mop *MulOp) ([]byte, error) {
	var results int64
	conn := oper.pool.Get()
	defer conn.Close()
	for _, k := range mop.keys {
		n, err := conn.Do("del", k)
		if err != nil {
			return nil, errors.Trace(err)
		}
		results += n.(int64)
	}

	b, err := respcoding.Marshal(int(results))
	return b, errors.Trace(err)
}
Beispiel #4
0
func (oper *MultiOperator) mgetResults(mop *MulOp) ([]byte, error) {
	results := make([]interface{}, len(mop.keys))
	conn := oper.pool.Get()
	defer conn.Close()
	for i, key := range mop.keys {
		replys, err := redis.Values(conn.Do("mget", key))
		if err != nil {
			return nil, errors.Trace(err)
		}

		for _, reply := range replys {
			if reply != nil {
				results[i] = reply
			} else {
				results[i] = nil
			}
		}
	}

	b, err := respcoding.Marshal(results)
	return b, errors.Trace(err)
}
Beispiel #5
0
func filter(opstr string, keys [][]byte, c *session, timeoutSec int) (rawresp []byte, next bool, err error) {
	if !allowOp(opstr) {
		errmsg, err := respcoding.Marshal(fmt.Errorf("%s not allowed", opstr))
		if err != nil {
			log.Fatal("should never happend", opstr)
		}
		return errmsg, false, errors.New(string(errmsg))
	}

	buf, shouldClose, handled, err := handleSpecCommand(opstr, keys, timeoutSec)
	if shouldClose { //quit command
		return buf, false, errors.Trace(io.EOF)
	}
	if err != nil {
		return nil, false, errors.Trace(err)
	}

	if handled {
		return buf, false, nil
	}

	return nil, true, nil
}
Beispiel #6
0
func handleSpecCommand(cmd string, clientWriter DeadlineReadWriter, keys [][]byte) (bool, bool, error) {
	var b []byte
	shouldClose := false
	switch cmd {
	case "PING":
		b = []byte("+PONG\r\n")
	case "QUIT":
		b = OK_BYTES
		shouldClose = true
	case "SELECT":
		b = OK_BYTES
	case "AUTH":
		b = OK_BYTES
	case "ECHO":
		if len(keys) > 0 {
			var err error
			b, err = respcoding.Marshal(string(keys[0]))
			if err != nil {
				return true, false, errors.Trace(err)
			}
		} else {
			return true, false, nil
		}
	}

	if len(b) > 0 {
		clientWriter.SetWriteDeadline(time.Now().Add(5 * time.Second))
		_, err := clientWriter.Write(b)
		if err != nil {
			return shouldClose, true, errors.Errorf("%s, cmd:%s", err.Error(), cmd)
		}

		return shouldClose, true, nil
	}

	return shouldClose, false, nil
}
Beispiel #7
0
func Parse(r *bufio.Reader) (*Resp, error) {
	line, err := readLine(r)
	if err != nil {
		return nil, errors.Trace(err)
	}

	resp := &Resp{Raw: line}

	switch line[0] {
	case '-':
		resp.Type = ErrorResp
		return resp, nil
	case '+':
		resp.Type = SimpleString
		return resp, nil
	case ':':
		resp.Type = IntegerResp
		return resp, nil
	case '$':
		resp.Type = BulkResp
		size, err := Btoi(line[1 : len(line)-2])
		if err != nil {
			return nil, errors.Trace(err)
		}
		err = ReadBulk(r, size, &resp.Raw)
		if err != nil {
			return nil, errors.Trace(err)
		}
		return resp, nil
	case '*':
		i, err := Btoi(line[1 : len(line)-2]) //strip \r\n
		if err != nil {
			return nil, errors.Trace(err)
		}
		resp.Type = MultiResp
		if i >= 0 {
			multi := make([]*Resp, i)
			for j := 0; j < i; j++ {
				rp, err := Parse(r)
				if err != nil {
					return nil, errors.Trace(err)
				}
				multi[j] = rp
			}
			resp.Multi = multi
		}
		return resp, nil
	default:
		if !IsLetter(line[0]) { //handle telnet text command
			return nil, errors.New("redis protocol error, " + string(line))
		}

		resp.Type = MultiResp
		strs := strings.Split(string(line), " ")

		resp.Raw = make([]byte, 0, 20)
		resp.Raw = append(resp.Raw, '*')
		resp.Raw = append(resp.Raw, []byte(strconv.Itoa(len(strs)))...)
		resp.Raw = append(resp.Raw, NEW_LINE...)
		for i := 0; i < len(strs); i++ { //last element is \r\n
			if str := strings.TrimSpace(strs[i]); len(str) > 0 {
				b, err := respcoding.Marshal(str)
				if err != nil {
					return nil, errors.New("redis protocol error, " + string(line))
				}

				resp.Multi = append(resp.Multi, &Resp{Type: BulkResp, Raw: b})
			}
		}
		return resp, nil
	}
}