func (parse *TextProtocolParse) release(conn *common.Conn, doClose bool) {
	if doClose {
		go conn.Close()
	} else {
		go parse.pool.Release(conn)
	}
}
Example #2
0
func (pool *ConnectionPool) release(i int, conn *common.Conn) {
	select {
	case pool.pools[i] <- conn:
	default:
		conn.Close()
	}
}
// fillPacket fill the send packet and write the packet to buffer.
func (parse *BinaryPorotolParse) fillPacket(p *packet, conn *common.Conn) (err error) {
	var header []byte = make([]byte, headerLen)
	var i int

	// fill request header
	header[i] = p.magic
	i += magicLen
	header[i] = p.opcode
	i += opcodeLen
	binary.BigEndian.PutUint16(header[i:i+keyLen], p.keyLength)
	i += keyLen
	header[i] = p.extrasLength
	i += extrasLen
	header[i] = p.dataType
	i += dataTypeLen
	binary.BigEndian.PutUint16(header[i:i+statusLen], p.statusOrVbucket)
	i += statusLen
	binary.BigEndian.PutUint32(header[i:i+totalBodyLen], p.totalBodyLength)
	i += totalBodyLen
	binary.BigEndian.PutUint32(header[i:i+opaqueLen], p.opaque)
	i += opaqueLen
	binary.BigEndian.PutUint64(header[i:i+casLen], p.cas)

	// write content to buffer
	_, err = conn.WriteToBuffer(header)
	_, err = conn.WriteToBuffer(p.extras)
	_, err = conn.WriteToBuffer(p.key)
	_, err = conn.WriteToBuffer(p.value)

	return
}
func (parse *BinaryPorotolParse) requestAndResponse(conn *common.Conn, reqPacket *packet) (resPacket *packet, err error) {
	if err = parse.fillPacket(reqPacket, conn); err != nil {
		parse.release(conn, true)
		return
	}

	if err = conn.Flush(); err != nil {
		parse.release(conn, true)
		return
	}

	if resPacket, err = parse.parsePacket(conn); err != nil {
		parse.release(conn, true)
		return
	} else {
		err = parse.checkError(resPacket.statusOrVbucket)
		parse.release(conn, false)
	}

	return
}
// parsePacket parse the response packet from serer.
func (parse *BinaryPorotolParse) parsePacket(conn *common.Conn) (p *packet, err error) {
	var header []byte = make([]byte, headerLen)
	var i, n int

	// read response header
	if n, err = conn.Read(header); err != nil {
		return
	} else if n != headerLen {
		err = errors.New("Memcached : Unknow error")
		return
	}

	// parse response header
	p = &packet{}
	p.magic = header[i]
	i += magicLen
	p.opcode = header[i]
	i += opcodeLen
	p.keyLength = binary.BigEndian.Uint16(header[i : i+keyLen])
	i += keyLen
	p.extrasLength = header[i]
	i += extrasLen
	p.dataType = header[i]
	i += dataTypeLen
	p.statusOrVbucket = binary.BigEndian.Uint16(header[i : i+statusLen])
	i += statusLen
	p.totalBodyLength = binary.BigEndian.Uint32(header[i : i+totalBodyLen])
	i += totalBodyLen
	p.opaque = binary.BigEndian.Uint32(header[i : i+opaqueLen])
	i += opaqueLen
	p.cas = binary.BigEndian.Uint64(header[i : i+casLen])

	// read extras from response if exist
	if p.extrasLength > 0 {
		p.extras = make([]byte, p.extrasLength)

		if n, err = conn.Read(p.extras); err != nil {
			return
		} else if n != int(p.extrasLength) {
			err = errors.New("Memcached : Unknow error")
			return
		}
	}

	// read key from response if exist
	if p.keyLength > 0 {
		p.key = make([]byte, p.keyLength)

		if n, err = conn.Read(p.key); err != nil {
			return
		} else if n != int(p.keyLength) {
			err = errors.New("Memcached : Unknow error")
			return
		}
	}

	// read value from response if exist
	valueLength := int(p.totalBodyLength) - int(p.keyLength) - int(p.extrasLength)
	if valueLength > 0 {
		p.value = make([]byte, valueLength)

		if n, err = conn.Read(p.value); err != nil {
			return
		} else if n != valueLength {
			err = errors.New("Memcached : Unknow error")
			return
		}
	}

	return
}