patch 4.0
This commit is contained in:
@ -20,34 +20,34 @@
|
||||
|
||||
using namespace oceanbase::common;
|
||||
|
||||
namespace oceanbase {
|
||||
namespace obmysql {
|
||||
void __attribute__((weak)) request_finish_callback()
|
||||
{}
|
||||
|
||||
ObMySQLRequestUtils::ObMySQLRequestUtils()
|
||||
{}
|
||||
|
||||
ObMySQLRequestUtils::~ObMySQLRequestUtils()
|
||||
{}
|
||||
|
||||
int ObMySQLRequestUtils::encode_packet(easy_buf_t* ez_buf, ObMySQLPacket& pkt, const uint8_t packet_seq)
|
||||
namespace oceanbase
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (OB_ISNULL(ez_buf)) {
|
||||
ret = OB_ERR_NULL_VALUE;
|
||||
SERVER_LOG(WARN, "invalid argument", K(ret), KP(ez_buf), K(pkt), K(packet_seq));
|
||||
namespace obmysql
|
||||
{
|
||||
void __attribute__((weak)) request_finish_callback() {}
|
||||
|
||||
ObMySQLRequestUtils::ObMySQLRequestUtils(){}
|
||||
|
||||
ObMySQLRequestUtils::~ObMySQLRequestUtils(){}
|
||||
|
||||
static int64_t get_max_comp_pkt_size(const int64_t uncomp_pkt_size)
|
||||
{
|
||||
int64_t ret_size = 0;
|
||||
if (uncomp_pkt_size > MAX_COMPRESSED_BUF_SIZE) {
|
||||
//limit max comp_buf_size is 2M-1k
|
||||
ret_size = MAX_COMPRESSED_BUF_SIZE;
|
||||
} else {
|
||||
int64_t seri_size = 0;
|
||||
// packet_seq is critical, when set wrong, client may disconnect
|
||||
pkt.set_seq(packet_seq);
|
||||
if (OB_FAIL(pkt.encode(ez_buf->last, ez_buf->end - ez_buf->last, seri_size))) {
|
||||
SERVER_LOG(WARN, "encode MySQL packet fail", "buf size", ez_buf->end - ez_buf->last);
|
||||
} else {
|
||||
ez_buf->last += seri_size;
|
||||
ret_size = (common::OB_MYSQL_COMPRESSED_HEADER_SIZE
|
||||
+ uncomp_pkt_size
|
||||
+ 13
|
||||
+ (uncomp_pkt_size >> 12)
|
||||
+ (uncomp_pkt_size >> 14)
|
||||
+ (uncomp_pkt_size >> 25));
|
||||
if (ret_size > MAX_COMPRESSED_BUF_SIZE) {
|
||||
ret_size = MAX_COMPRESSED_BUF_SIZE;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
return ret_size;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -58,15 +58,13 @@ int ObMySQLRequestUtils::encode_packet(easy_buf_t* ez_buf, ObMySQLPacket& pkt, c
|
||||
*
|
||||
* the body is compressed packet(orig header + orig body)
|
||||
*
|
||||
* http://imysql.com/mysql-internal-manual/compressed-packet-header.html
|
||||
*
|
||||
* NOTE: In standard mysql compress protocol, if src_pktlen < 50B, or compr_pktlen >= src_pktlen
|
||||
* mysql will do not compress it and set pktlen_before_compression = 0,
|
||||
* it can not ensure checksum.
|
||||
* NOTE: In OB, we need always checksum ensured first!
|
||||
*/
|
||||
int ObMySQLRequestUtils::build_compressed_packet(
|
||||
ObEasyBuffer& src_buf, const int64_t next_compress_size, ObCompressionContext& context)
|
||||
static int build_compressed_packet(ObEasyBuffer &src_buf,
|
||||
const int64_t next_compress_size, ObCompressionContext &context)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (OB_ISNULL(context.send_buf_)) {
|
||||
@ -85,46 +83,37 @@ int ObMySQLRequestUtils::build_compressed_packet(
|
||||
int64_t pos = 0;
|
||||
int64_t len_before_compress = 0;
|
||||
if (use_real_compress) {
|
||||
if (OB_FAIL(compressor.compress(src_buf.read_pos(),
|
||||
next_compress_size,
|
||||
dst_buf.last() + OB_MYSQL_COMPRESSED_HEADER_SIZE,
|
||||
comp_buf_size,
|
||||
dst_data_size))) {
|
||||
if (OB_FAIL(compressor.compress(src_buf.read_pos(), next_compress_size,
|
||||
dst_buf.last() + OB_MYSQL_COMPRESSED_HEADER_SIZE,
|
||||
comp_buf_size, dst_data_size))) {
|
||||
SERVER_LOG(WARN, "compress packet failed", K(ret));
|
||||
} else if (OB_UNLIKELY(dst_data_size > comp_buf_size)) {
|
||||
ret = OB_SIZE_OVERFLOW;
|
||||
SERVER_LOG(
|
||||
WARN, "dst_data_size is overflow, it should not happened", K(dst_data_size), K(comp_buf_size), K(ret));
|
||||
SERVER_LOG(WARN, "dst_data_size is overflow, it should not happened",
|
||||
K(dst_data_size), K(comp_buf_size), K(ret));
|
||||
} else {
|
||||
len_before_compress = next_compress_size;
|
||||
}
|
||||
} else {
|
||||
// if compress off, just copy date to output buf
|
||||
//if compress off, just copy date to output buf
|
||||
MEMCPY(dst_buf.last() + OB_MYSQL_COMPRESSED_HEADER_SIZE, src_buf.read_pos(), next_compress_size);
|
||||
dst_data_size = next_compress_size;
|
||||
len_before_compress = 0;
|
||||
}
|
||||
|
||||
if (FAILEDx(ObMySQLUtil::store_int3(
|
||||
dst_buf.last(), OB_MYSQL_COMPRESSED_HEADER_SIZE, static_cast<int32_t>(dst_data_size), pos))) {
|
||||
if (FAILEDx(ObMySQLUtil::store_int3(dst_buf.last(), OB_MYSQL_COMPRESSED_HEADER_SIZE,
|
||||
static_cast<int32_t>(dst_data_size), pos))) {
|
||||
SERVER_LOG(WARN, "failed to store_int3", K(ret));
|
||||
} else if (OB_FAIL(ObMySQLUtil::store_int1(dst_buf.last(), OB_MYSQL_COMPRESSED_HEADER_SIZE, context.seq_, pos))) {
|
||||
} else if (OB_FAIL(ObMySQLUtil::store_int1(dst_buf.last(), OB_MYSQL_COMPRESSED_HEADER_SIZE,
|
||||
context.seq_, pos))) {
|
||||
SERVER_LOG(WARN, "failed to store_int1", K(ret));
|
||||
} else if (OB_FAIL(ObMySQLUtil::store_int3(
|
||||
dst_buf.last(), OB_MYSQL_COMPRESSED_HEADER_SIZE, static_cast<int32_t>(len_before_compress), pos))) {
|
||||
} else if (OB_FAIL(ObMySQLUtil::store_int3(dst_buf.last(), OB_MYSQL_COMPRESSED_HEADER_SIZE,
|
||||
static_cast<int32_t>(len_before_compress), pos))) {
|
||||
SERVER_LOG(WARN, "failed to store_int3", K(ret));
|
||||
} else {
|
||||
SERVER_LOG(DEBUG,
|
||||
"succ to build compressed pkt",
|
||||
"comp_len",
|
||||
dst_data_size,
|
||||
"comp_seq",
|
||||
context.seq_,
|
||||
K(len_before_compress),
|
||||
K(next_compress_size),
|
||||
K(src_buf),
|
||||
K(dst_buf),
|
||||
K(context));
|
||||
SERVER_LOG(DEBUG, "succ to build compressed pkt", "comp_len", dst_data_size,
|
||||
"comp_seq", context.seq_, K(len_before_compress), K(next_compress_size),
|
||||
K(src_buf), K(dst_buf), K(context));
|
||||
src_buf.read(next_compress_size);
|
||||
dst_buf.write(dst_data_size + OB_MYSQL_COMPRESSED_HEADER_SIZE);
|
||||
++context.seq_;
|
||||
@ -133,27 +122,123 @@ int ObMySQLRequestUtils::build_compressed_packet(
|
||||
return ret;
|
||||
}
|
||||
|
||||
// Deprecated
|
||||
// once flushed ObRequest may be destroyed
|
||||
int ObMySQLRequestUtils::flush_buffer(easy_buf_t* ez_buf, rpc::ObRequest* req)
|
||||
static int build_compressed_buffer(ObEasyBuffer &orig_send_buf,
|
||||
ObCompressionContext &context)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (OB_ISNULL(ez_buf) || OB_ISNULL(req)) {
|
||||
ret = OB_ERR_NULL_VALUE;
|
||||
SERVER_LOG(ERROR, "invalid argument", K(ret), K(ez_buf), K(req));
|
||||
} else if (OB_ISNULL(req->get_ez_req()) || OB_ISNULL(req->get_ez_req()->ms) || OB_ISNULL(req->get_ez_req()->ms->c)) {
|
||||
ret = OB_ERR_NULL_VALUE;
|
||||
SERVER_LOG(ERROR, "ez_req_ is null", K(ret));
|
||||
} else {
|
||||
req->get_ez_req()->opacket = ez_buf;
|
||||
req->get_ez_req()->retcode = EASY_OK;
|
||||
wakeup_request(req);
|
||||
if (NULL != context.send_buf_) {
|
||||
ObEasyBuffer comp_send_buf(*context.send_buf_);
|
||||
if (OB_UNLIKELY(!orig_send_buf.is_valid()) || OB_UNLIKELY(!comp_send_buf.is_valid())) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
SERVER_LOG(ERROR, "orig_send_buf or comp_send_buf is invalid", K(orig_send_buf), K(comp_send_buf), K(ret));
|
||||
} else {
|
||||
const int64_t max_read_step = context.get_max_read_step();
|
||||
int64_t next_read_size = orig_send_buf.get_next_read_size(context.last_pkt_pos_, max_read_step);
|
||||
int64_t last_read_size = 0;
|
||||
int64_t max_comp_pkt_size = get_max_comp_pkt_size(next_read_size);
|
||||
while (OB_SUCC(ret)
|
||||
&& next_read_size > 0
|
||||
&& max_comp_pkt_size <= comp_send_buf.write_avail_size()) {
|
||||
//error+ok/ok packet should use last seq
|
||||
if (context.last_pkt_pos_ == orig_send_buf.read_pos() && context.is_proxy_compress_based()) {
|
||||
--context.seq_;
|
||||
}
|
||||
|
||||
if (OB_FAIL(build_compressed_packet(orig_send_buf, next_read_size, context))) {
|
||||
SERVER_LOG(WARN, "fail to build_compressed_packet", K(ret));
|
||||
} else {
|
||||
//optimize for multi packet
|
||||
last_read_size = next_read_size;
|
||||
next_read_size = orig_send_buf.get_next_read_size(context.last_pkt_pos_, max_read_step);
|
||||
if (last_read_size != next_read_size) {
|
||||
max_comp_pkt_size = get_max_comp_pkt_size(next_read_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObMySQLRequestUtils::flush_buffer_internal(
|
||||
easy_buf_t* send_buf, ObFlushBufferParam& param, const bool is_last_flush)
|
||||
static int reuse_compress_buffer(ObCompressionContext &comp_context, ObEasyBuffer &orig_send_buf,
|
||||
int64_t comp_buf_size, rpc::ObRequest &req)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
bool need_alloc = false;
|
||||
if (NULL == comp_context.send_buf_) {
|
||||
need_alloc = true;
|
||||
//use buf_size to avoid alloc again next time
|
||||
comp_buf_size = get_max_comp_pkt_size(orig_send_buf.orig_buf_size());
|
||||
} else {
|
||||
const int64_t new_size = get_max_comp_pkt_size(orig_send_buf.read_avail_size());
|
||||
if (new_size <= comp_buf_size) {
|
||||
//reusing last size is enough
|
||||
} else {
|
||||
SERVER_LOG(DEBUG, "need resize compressed buf", "old_size", comp_buf_size, K(new_size),
|
||||
"orig_send_buf_", orig_send_buf);
|
||||
//realloc
|
||||
comp_buf_size = new_size;
|
||||
need_alloc = true;
|
||||
}
|
||||
}
|
||||
|
||||
//alloc if necessary
|
||||
if (need_alloc) {
|
||||
const uint32_t size = static_cast<uint32_t>(comp_buf_size + sizeof(easy_buf_t));
|
||||
if (OB_ISNULL(comp_context.send_buf_ =
|
||||
reinterpret_cast<easy_buf_t *>(SQL_REQ_OP.alloc_sql_response_buffer(&req, size)))) {
|
||||
ret = OB_ALLOCATE_MEMORY_FAILED;
|
||||
SERVER_LOG(ERROR, "allocate memory failed", K(size), K(ret));
|
||||
}
|
||||
}
|
||||
|
||||
//reuse
|
||||
if (OB_SUCC(ret)) {
|
||||
init_easy_buf(comp_context.send_buf_,
|
||||
reinterpret_cast<char *>(comp_context.send_buf_ + 1),
|
||||
NULL, comp_buf_size);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int send_compressed_buffer(bool pkt_has_completed, ObCompressionContext &comp_context,
|
||||
ObEasyBuffer &orig_send_buf, rpc::ObRequest &req)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
const bool is_last_flush = pkt_has_completed && !orig_send_buf.is_read_avail();
|
||||
int64_t buf_size = 0;
|
||||
int64_t read_avail_size = 0;
|
||||
|
||||
if (NULL != comp_context.send_buf_) {
|
||||
ObEasyBuffer comp_send_buf(*comp_context.send_buf_);
|
||||
buf_size = comp_send_buf.orig_buf_size();
|
||||
read_avail_size = comp_send_buf.read_avail_size();
|
||||
}
|
||||
|
||||
if (read_avail_size > 0) {
|
||||
if (is_last_flush) {
|
||||
if (OB_FAIL(SQL_REQ_OP.async_write_response(&req, comp_context.send_buf_->pos, read_avail_size))) {
|
||||
SERVER_LOG(WARN, "failed to flush buffer", K(ret));
|
||||
}
|
||||
} else {
|
||||
if (OB_FAIL(SQL_REQ_OP.write_response(&req, comp_context.send_buf_->pos, read_avail_size))) {
|
||||
SERVER_LOG(WARN, "failed to flush buffer", K(ret));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (OB_SUCC(ret) && !is_last_flush) {
|
||||
if (OB_FAIL(reuse_compress_buffer(comp_context, orig_send_buf, buf_size, req))) {
|
||||
SERVER_LOG(WARN, "faild to reuse_compressed_buffer_sql_nio", K(ret));
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObMySQLRequestUtils::flush_buffer_internal(easy_buf_t *send_buf,
|
||||
ObFlushBufferParam ¶m, const bool is_last_flush)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (OB_UNLIKELY(!param.conn_valid_)) {
|
||||
@ -163,14 +248,14 @@ int ObMySQLRequestUtils::flush_buffer_internal(
|
||||
} else if (param.req_has_wokenup_) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
SERVER_LOG(ERROR, "req_has_wokenup, resource maybe has destroy", K(ret));
|
||||
} else if (OB_ISNULL(param.ez_req_.ms) || OB_ISNULL(param.ez_req_.ms->c) ||
|
||||
OB_UNLIKELY(param.ez_req_.ms->c->conn_has_error)) {
|
||||
} else if (OB_ISNULL(param.ez_req_.ms) || OB_ISNULL(param.ez_req_.ms->c)
|
||||
|| OB_UNLIKELY(param.ez_req_.ms->c->conn_has_error)) {
|
||||
ret = OB_CONNECT_ERROR;
|
||||
SERVER_LOG(WARN, "connection has error", KP(param.ez_req_.ms), K(ret));
|
||||
wakeup_easy_request(param.ez_req_, param.req_has_wokenup_, param.io_thread_mark_);
|
||||
wakeup_easy_request(param.ez_req_, param.req_has_wokenup_);
|
||||
param.conn_valid_ = false;
|
||||
} else {
|
||||
// flush it only if data contained
|
||||
//flush it only if data contained
|
||||
if (NULL != send_buf && send_buf->last > send_buf->pos) {
|
||||
param.ez_req_.opacket = send_buf;
|
||||
} else {
|
||||
@ -179,7 +264,7 @@ int ObMySQLRequestUtils::flush_buffer_internal(
|
||||
|
||||
if (is_last_flush) {
|
||||
param.ez_req_.retcode = EASY_OK;
|
||||
wakeup_easy_request(param.ez_req_, param.req_has_wokenup_, param.io_thread_mark_);
|
||||
wakeup_easy_request(param.ez_req_, param.req_has_wokenup_);
|
||||
|
||||
} else {
|
||||
easy_client_wait_t wait_obj;
|
||||
@ -189,7 +274,7 @@ int ObMySQLRequestUtils::flush_buffer_internal(
|
||||
param.ez_req_.client_wait = &wait_obj;
|
||||
param.ez_req_.retcode = EASY_AGAIN;
|
||||
param.ez_req_.waiting = 1;
|
||||
wakeup_easy_request(param.ez_req_, param.req_has_wokenup_, param.io_thread_mark_);
|
||||
wakeup_easy_request(param.ez_req_, param.req_has_wokenup_);
|
||||
|
||||
// wait for wake up by IO thread in `process' callback
|
||||
{
|
||||
@ -209,20 +294,21 @@ int ObMySQLRequestUtils::flush_buffer_internal(
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObMySQLRequestUtils::check_flush_param(ObFlushBufferParam& param)
|
||||
int ObMySQLRequestUtils::check_flush_param(ObFlushBufferParam ¶m)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (OB_ISNULL(param.ez_req_.ms) || OB_ISNULL(param.ez_req_.ms->pool) || OB_ISNULL(param.ez_req_.ms->c) ||
|
||||
OB_UNLIKELY(param.ez_req_.ms->c->conn_has_error)) {
|
||||
if (OB_ISNULL(param.ez_req_.ms) || OB_ISNULL(param.ez_req_.ms->pool)
|
||||
|| OB_ISNULL(param.ez_req_.ms->c) || OB_UNLIKELY(param.ez_req_.ms->c->conn_has_error)) {
|
||||
ret = OB_CONNECT_ERROR;
|
||||
SERVER_LOG(WARN, "connection has error", KP(param.ez_req_.ms), K(ret));
|
||||
wakeup_easy_request(param.ez_req_, param.req_has_wokenup_, param.io_thread_mark_);
|
||||
wakeup_easy_request(param.ez_req_, param.req_has_wokenup_);
|
||||
param.conn_valid_ = false;
|
||||
} else if (OB_UNLIKELY(!param.orig_send_buf_.is_valid())) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
SERVER_LOG(ERROR, "orig_send_buf_ is invalid", K(param.orig_send_buf_), K(ret));
|
||||
} else if (!param.comp_context_.use_compress()) {
|
||||
if (OB_NOT_NULL(param.comp_context_.last_pkt_pos_) || OB_NOT_NULL(param.comp_context_.send_buf_)) {
|
||||
if (OB_NOT_NULL(param.comp_context_.last_pkt_pos_)
|
||||
|| OB_NOT_NULL(param.comp_context_.send_buf_)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
SERVER_LOG(ERROR, "last_pkt_pos_ or send_buf is not null", K(param.comp_context_), K(ret));
|
||||
}
|
||||
@ -234,11 +320,8 @@ int ObMySQLRequestUtils::check_flush_param(ObFlushBufferParam& param)
|
||||
} else if (param.comp_context_.is_proxy_compress_based()) {
|
||||
if (NULL == param.comp_context_.last_pkt_pos_ && param.pkt_has_completed_ && param.orig_send_buf_.is_read_avail()) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
SERVER_LOG(WARN,
|
||||
"this is last flush, but without proxy last pkt pos",
|
||||
K(param.comp_context_),
|
||||
K(param.orig_send_buf_),
|
||||
K(ret));
|
||||
SERVER_LOG(WARN, "this is last flush, but without proxy last pkt pos",
|
||||
K(param.comp_context_), K(param.orig_send_buf_), K(ret));
|
||||
} else if (NULL != param.comp_context_.last_pkt_pos_) {
|
||||
/*
|
||||
* pos ppos last end
|
||||
@ -250,68 +333,27 @@ int ObMySQLRequestUtils::check_flush_param(ObFlushBufferParam& param)
|
||||
* 4) ppos=last, send_buf's data is normal packet
|
||||
* 5) pos<ppos<last, send_buf's data is normal[pos, ppos) + proxy last packet[idx, last)
|
||||
* */
|
||||
if (OB_UNLIKELY(param.comp_context_.last_pkt_pos_ > param.orig_send_buf_.last()) ||
|
||||
OB_UNLIKELY(param.comp_context_.last_pkt_pos_ < param.orig_send_buf_.read_pos())) {
|
||||
if (OB_UNLIKELY(param.comp_context_.last_pkt_pos_ > param.orig_send_buf_.last())
|
||||
|| OB_UNLIKELY(param.comp_context_.last_pkt_pos_ < param.orig_send_buf_.read_pos())) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
SERVER_LOG(ERROR,
|
||||
"last_pkt_pos_ is out of range",
|
||||
KP_(param.comp_context_.last_pkt_pos),
|
||||
KP(param.orig_send_buf_.read_pos()),
|
||||
KP(param.orig_send_buf_.last()),
|
||||
K(ret));
|
||||
SERVER_LOG(ERROR, "last_pkt_pos_ is out of range", KP_(param.comp_context_.last_pkt_pos),
|
||||
KP(param.orig_send_buf_.read_pos()), KP(param.orig_send_buf_.last()), K(ret));
|
||||
} else if (param.orig_send_buf_.proxy_read_avail_size(param.comp_context_.last_pkt_pos_) >
|
||||
MAX_COMPRESSED_BUF_SIZE) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
SERVER_LOG(ERROR,
|
||||
"proxy last pkt size is too large",
|
||||
K(ret),
|
||||
K(MAX_COMPRESSED_BUF_SIZE),
|
||||
"size",
|
||||
param.orig_send_buf_.proxy_read_avail_size(param.comp_context_.last_pkt_pos_));
|
||||
SERVER_LOG(ERROR, "proxy last pkt size is too large", K(ret),
|
||||
K(MAX_COMPRESSED_BUF_SIZE),
|
||||
"size", param.orig_send_buf_.proxy_read_avail_size(param.comp_context_.last_pkt_pos_));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// do nothing
|
||||
//do nothing
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObMySQLRequestUtils::build_compressed_buffer(ObEasyBuffer& orig_send_buf, ObCompressionContext& context)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (NULL != context.send_buf_) {
|
||||
ObEasyBuffer comp_send_buf(*context.send_buf_);
|
||||
if (OB_UNLIKELY(!orig_send_buf.is_valid()) || OB_UNLIKELY(!comp_send_buf.is_valid())) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
SERVER_LOG(ERROR, "orig_send_buf or comp_send_buf is invalid", K(orig_send_buf), K(comp_send_buf), K(ret));
|
||||
} else {
|
||||
const int64_t max_read_step = context.get_max_read_step();
|
||||
int64_t next_read_size = orig_send_buf.get_next_read_size(context.last_pkt_pos_, max_read_step);
|
||||
int64_t last_read_size = 0;
|
||||
int64_t max_comp_pkt_size = get_max_comp_pkt_size(next_read_size);
|
||||
while (OB_SUCC(ret) && next_read_size > 0 && max_comp_pkt_size <= comp_send_buf.write_avail_size()) {
|
||||
// error+ok/ok packet should use last seq
|
||||
if (context.last_pkt_pos_ == orig_send_buf.read_pos() && context.is_proxy_compress_based()) {
|
||||
--context.seq_;
|
||||
}
|
||||
|
||||
if (OB_FAIL(build_compressed_packet(orig_send_buf, next_read_size, context))) {
|
||||
SERVER_LOG(WARN, "fail to build_compressed_packet", K(ret));
|
||||
} else {
|
||||
// optimize for multi packet
|
||||
last_read_size = next_read_size;
|
||||
next_read_size = orig_send_buf.get_next_read_size(context.last_pkt_pos_, max_read_step);
|
||||
if (last_read_size != next_read_size) {
|
||||
max_comp_pkt_size = get_max_comp_pkt_size(next_read_size);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObMySQLRequestUtils::consume_compressed_buffer(ObFlushBufferParam& param, const bool flush_immediately /*false*/)
|
||||
int ObMySQLRequestUtils::consume_compressed_buffer(ObFlushBufferParam ¶m,
|
||||
const bool flush_immediately/*false*/)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
const bool is_last_flush = param.pkt_has_completed_ && !param.orig_send_buf_.is_read_avail();
|
||||
@ -323,7 +365,7 @@ int ObMySQLRequestUtils::consume_compressed_buffer(ObFlushBufferParam& param, co
|
||||
read_avail_size = comp_send_buf.read_avail_size();
|
||||
}
|
||||
|
||||
// 1. flush it
|
||||
//1. flush it
|
||||
if (read_avail_size > 0 || flush_immediately) {
|
||||
if (OB_FAIL(flush_buffer_internal(param.comp_context_.send_buf_, param, is_last_flush))) {
|
||||
SERVER_LOG(WARN, "failed to flush_buffer", K(ret));
|
||||
@ -332,7 +374,7 @@ int ObMySQLRequestUtils::consume_compressed_buffer(ObFlushBufferParam& param, co
|
||||
}
|
||||
}
|
||||
|
||||
// 2. reuse it
|
||||
//2. reuse it
|
||||
if (OB_SUCC(ret) && !is_last_flush) {
|
||||
if (OB_FAIL(reuse_compressed_buffer(param, buf_size, is_last_flush))) {
|
||||
SERVER_LOG(WARN, "fail to reuse_compressed_buffer", K(ret));
|
||||
@ -343,172 +385,145 @@ int ObMySQLRequestUtils::consume_compressed_buffer(ObFlushBufferParam& param, co
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObMySQLRequestUtils::reuse_compressed_buffer(
|
||||
ObFlushBufferParam& param, int64_t comp_buf_size, const bool is_last_flush)
|
||||
int ObMySQLRequestUtils::reuse_compressed_buffer(ObFlushBufferParam ¶m,
|
||||
int64_t comp_buf_size, const bool is_last_flush)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
bool need_alloc = false;
|
||||
if (NULL == param.comp_context_.send_buf_) {
|
||||
need_alloc = true;
|
||||
if (is_last_flush) {
|
||||
// use data size is enough
|
||||
//use data size is enough
|
||||
comp_buf_size = get_max_comp_pkt_size(param.orig_send_buf_.orig_data_size());
|
||||
} else {
|
||||
// use buf_size to avoid alloc again next time
|
||||
//use buf_size to avoid alloc again next time
|
||||
comp_buf_size = get_max_comp_pkt_size(param.orig_send_buf_.orig_buf_size());
|
||||
}
|
||||
} else {
|
||||
const int64_t new_size = get_max_comp_pkt_size(param.orig_send_buf_.read_avail_size());
|
||||
if (new_size <= comp_buf_size) {
|
||||
// reusing last size is enough
|
||||
//reusing last size is enough
|
||||
} else {
|
||||
SERVER_LOG(DEBUG,
|
||||
"need resize compressed buf",
|
||||
"old_size",
|
||||
comp_buf_size,
|
||||
K(new_size),
|
||||
"orig_send_buf_",
|
||||
param.orig_send_buf_);
|
||||
// realloc
|
||||
SERVER_LOG(DEBUG, "need resize compressed buf", "old_size", comp_buf_size, K(new_size),
|
||||
"orig_send_buf_", param.orig_send_buf_);
|
||||
//realloc
|
||||
comp_buf_size = new_size;
|
||||
need_alloc = true;
|
||||
}
|
||||
}
|
||||
|
||||
// alloc if necessary
|
||||
//alloc if necessary
|
||||
if (need_alloc) {
|
||||
const uint32_t size = static_cast<uint32_t>(comp_buf_size + sizeof(easy_buf_t));
|
||||
if (OB_ISNULL(param.comp_context_.send_buf_ =
|
||||
reinterpret_cast<easy_buf_t*>(easy_pool_alloc(param.ez_req_.ms->pool, size)))) {
|
||||
reinterpret_cast<easy_buf_t *>(easy_pool_alloc(param.ez_req_.ms->pool, size)))) {
|
||||
ret = OB_ALLOCATE_MEMORY_FAILED;
|
||||
SERVER_LOG(ERROR, "allocate memory failed", K(size), K(ret));
|
||||
}
|
||||
}
|
||||
|
||||
// reuse
|
||||
//reuse
|
||||
if (OB_SUCC(ret)) {
|
||||
init_easy_buf(param.comp_context_.send_buf_,
|
||||
reinterpret_cast<char*>(param.comp_context_.send_buf_ + 1),
|
||||
¶m.ez_req_,
|
||||
comp_buf_size);
|
||||
reinterpret_cast<char *>(param.comp_context_.send_buf_ + 1),
|
||||
¶m.ez_req_, comp_buf_size);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObMySQLRequestUtils::flush_buffer(ObFlushBufferParam& param)
|
||||
int ObMySQLRequestUtils::flush_buffer(ObFlushBufferParam ¶m)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (OB_FAIL(check_flush_param(param))) {
|
||||
SERVER_LOG(WARN, "failed to check_flush_param", K(ret));
|
||||
} else if (!param.comp_context_.use_compress()) {
|
||||
// use no compress
|
||||
//use no compress
|
||||
// easy_wakeup will move buf.pos to buf.last, so orig_buf_size() after flush is not the original buf length
|
||||
const int64_t buf_size = param.orig_send_buf_.orig_buf_size();
|
||||
if (OB_FAIL(flush_buffer_internal(¶m.orig_send_buf_.buf_, param, param.pkt_has_completed_))) {
|
||||
SERVER_LOG(WARN, "failed to flush_buffer", K(ret));
|
||||
} else if (!param.pkt_has_completed_) {
|
||||
init_easy_buf(¶m.orig_send_buf_.buf_,
|
||||
reinterpret_cast<char*>(¶m.orig_send_buf_.buf_ + 1),
|
||||
¶m.ez_req_,
|
||||
buf_size);
|
||||
init_easy_buf(¶m.orig_send_buf_.buf_, reinterpret_cast<char *>(¶m.orig_send_buf_.buf_ + 1),
|
||||
¶m.ez_req_, buf_size);
|
||||
}
|
||||
}
|
||||
|
||||
// use compress
|
||||
//use compress
|
||||
if (OB_SUCC(ret) && param.comp_context_.use_compress()) {
|
||||
int64_t need_hold_size = 0;
|
||||
|
||||
// 1. save orig_send_buf hold_pos and size
|
||||
//1. save orig_send_buf hold_pos and size
|
||||
if (param.comp_context_.need_hold_last_pkt(param.pkt_has_completed_)) {
|
||||
need_hold_size = param.orig_send_buf_.proxy_read_avail_size(param.comp_context_.last_pkt_pos_);
|
||||
// NOTE::data still leave at orig_send_buf, we can still get it before reuse orig_send_buf
|
||||
//NOTE::data still leave at orig_send_buf, we can still get it before reuse orig_send_buf
|
||||
param.orig_send_buf_.write(0 - need_hold_size);
|
||||
SERVER_LOG(DEBUG, "need hold uncompleted proxy pkt", K(need_hold_size), "orig_send_buf", param.orig_send_buf_);
|
||||
SERVER_LOG(DEBUG, "need hold uncompleted proxy pkt", K(need_hold_size),
|
||||
"orig_send_buf", param.orig_send_buf_);
|
||||
}
|
||||
|
||||
// 2. compress --> flush --> reuse
|
||||
//2. compress --> flush --> reuse
|
||||
if (!param.orig_send_buf_.is_read_avail()) {
|
||||
// empty orig_send_buf, just flush immediately
|
||||
//empty orig_send_buf, just flush immediately
|
||||
const bool immediately = true;
|
||||
if (OB_FAIL(consume_compressed_buffer(param, immediately))) {
|
||||
SERVER_LOG(WARN, "fail to consume_compressed_buffer", K(ret));
|
||||
} else {
|
||||
// do nothing
|
||||
//do nothing
|
||||
}
|
||||
} else {
|
||||
// flush until orig_send_buf become empty
|
||||
while (OB_SUCC(ret) && !param.req_has_wokenup_ && param.orig_send_buf_.is_read_avail()) {
|
||||
//flush until orig_send_buf become empty
|
||||
while (OB_SUCC(ret)
|
||||
&& !param.req_has_wokenup_
|
||||
&& param.orig_send_buf_.is_read_avail()) {
|
||||
if (OB_FAIL(build_compressed_buffer(param.orig_send_buf_, param.comp_context_))) {
|
||||
SERVER_LOG(WARN, "fail to build_compressed_buffer", K(ret));
|
||||
} else if (OB_FAIL(consume_compressed_buffer(param))) {
|
||||
SERVER_LOG(WARN, "fail to consume_compressed_buffer", K(ret));
|
||||
} else {
|
||||
// do nothing
|
||||
//do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 3. reuse orig_send_buf and restore hold data
|
||||
//3. reuse orig_send_buf and restore hold data
|
||||
if (OB_SUCC(ret) && !param.pkt_has_completed_) {
|
||||
const bool need_reset_last_pkt_pos = (param.comp_context_.last_pkt_pos_ == param.orig_send_buf_.last());
|
||||
// reuse send_buf
|
||||
init_easy_buf(¶m.orig_send_buf_.buf_,
|
||||
reinterpret_cast<char*>(¶m.orig_send_buf_.buf_ + 1),
|
||||
¶m.ez_req_,
|
||||
param.orig_send_buf_.orig_buf_size());
|
||||
//reuse send_buf
|
||||
init_easy_buf(¶m.orig_send_buf_.buf_, reinterpret_cast<char *>(¶m.orig_send_buf_.buf_ + 1),
|
||||
¶m.ez_req_, param.orig_send_buf_.orig_buf_size());
|
||||
|
||||
// NOTE::data still leave at orig_send_buf, we can still get it before reuse orig_send_buf
|
||||
//NOTE::data still leave at orig_send_buf, we can still get it before reuse orig_send_buf
|
||||
if (need_reset_last_pkt_pos) {
|
||||
if (need_hold_size > 0) {
|
||||
MEMMOVE(param.orig_send_buf_.last(), param.comp_context_.last_pkt_pos_, need_hold_size);
|
||||
param.orig_send_buf_.write(need_hold_size);
|
||||
}
|
||||
|
||||
// if last_pkt_pos_, we need reset to pos after reuse send_buf
|
||||
//if last_pkt_pos_, we need reset to pos after reuse send_buf
|
||||
param.comp_context_.last_pkt_pos_ = param.orig_send_buf_.begin();
|
||||
SERVER_LOG(DEBUG,
|
||||
"need reset last_pkt_pos",
|
||||
K(need_hold_size),
|
||||
"orig_send_buf_",
|
||||
param.orig_send_buf_,
|
||||
"comp_context",
|
||||
param.comp_context_);
|
||||
SERVER_LOG(DEBUG, "need reset last_pkt_pos", K(need_hold_size),
|
||||
"orig_send_buf_", param.orig_send_buf_,
|
||||
"comp_context", param.comp_context_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if error had happened, libeasy must wakeup
|
||||
//if error had happened, libeasy must wakeup
|
||||
if (OB_FAIL(ret) && param.conn_valid_) {
|
||||
// Here is other potential bug that connection may be shut down twice and easy request may be
|
||||
// waken up twice if response is sent synchronously. We will not change it this time. It needs
|
||||
// to be redesigned in higher level.
|
||||
SERVER_LOG(WARN, "failed to flush buffer, and need close connection and wake up easy request.", K(ret));
|
||||
disconnect(param.ez_req_);
|
||||
wakeup_easy_request(param.ez_req_, param.req_has_wokenup_, param.io_thread_mark_);
|
||||
wakeup_easy_request(param.ez_req_, param.req_has_wokenup_);
|
||||
param.conn_valid_ = false;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObMySQLRequestUtils::wakeup_request(rpc::ObRequest* req)
|
||||
void ObMySQLRequestUtils::wakeup_easy_request(easy_request_t &ez_req, bool &req_has_wokenup)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (OB_ISNULL(req) || OB_ISNULL(req->get_request())) {
|
||||
ret = OB_ERR_NULL_VALUE;
|
||||
SERVER_LOG(WARN, "null req input", KP(req), K(ret));
|
||||
} else {
|
||||
if (req->get_request() != nullptr && req->get_request()->retcode != EASY_AGAIN) {
|
||||
request_finish_callback();
|
||||
}
|
||||
easy_request_wakeup(req->get_request());
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void ObMySQLRequestUtils::wakeup_easy_request(
|
||||
easy_request_t& ez_req, bool& req_has_wokenup, const bool io_thread_mark /*false*/)
|
||||
{
|
||||
if (!io_thread_mark && !req_has_wokenup) {
|
||||
if (!req_has_wokenup) {
|
||||
if (ez_req.retcode != EASY_AGAIN) {
|
||||
req_has_wokenup = true;
|
||||
request_finish_callback();
|
||||
@ -517,7 +532,7 @@ void ObMySQLRequestUtils::wakeup_easy_request(
|
||||
}
|
||||
}
|
||||
|
||||
void ObMySQLRequestUtils::disconnect(easy_request_t& ez_req)
|
||||
void ObMySQLRequestUtils::disconnect(easy_request_t &ez_req)
|
||||
{
|
||||
if (OB_ISNULL(ez_req.ms)) {
|
||||
SERVER_LOG(WARN, "null req input", KP(ez_req.ms));
|
||||
@ -526,7 +541,7 @@ void ObMySQLRequestUtils::disconnect(easy_request_t& ez_req)
|
||||
}
|
||||
}
|
||||
|
||||
int ObMysqlPktContext::save_fragment_mysql_packet(const char* start, const int64_t len)
|
||||
int ObMysqlPktContext::save_fragment_mysql_packet(const char *start, const int64_t len)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (OB_ISNULL(start) || len <= 0) {
|
||||
@ -542,12 +557,12 @@ int ObMysqlPktContext::save_fragment_mysql_packet(const char* start, const int64
|
||||
SERVER_LOG(ERROR, "invalid alloc size", K(alloc_size), K(ret));
|
||||
} else {
|
||||
alloc_size += payload_buffered_total_len_;
|
||||
char* tmp_buffer = reinterpret_cast<char*>(arena_.alloc(alloc_size));
|
||||
char *tmp_buffer = reinterpret_cast<char *>(arena_.alloc(alloc_size));
|
||||
if (OB_ISNULL(tmp_buffer)) {
|
||||
ret = OB_ALLOCATE_MEMORY_FAILED;
|
||||
SERVER_LOG(ERROR, "fail to alloc memory", K(alloc_size), K(ret));
|
||||
} else {
|
||||
if (payload_buffered_total_len_ > 0) { // skip the first alloc
|
||||
if (payload_buffered_total_len_ > 0) { // skip the first alloc
|
||||
MEMCPY(tmp_buffer, payload_buf_, payload_buffered_total_len_);
|
||||
}
|
||||
payload_buf_alloc_len_ = alloc_size;
|
||||
@ -559,7 +574,8 @@ int ObMysqlPktContext::save_fragment_mysql_packet(const char* start, const int64
|
||||
if (OB_SUCC(ret)) {
|
||||
if (OB_UNLIKELY(payload_buf_alloc_len_ < (payload_buffered_total_len_ + len))) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
SERVER_LOG(ERROR, "invalid buf len", K_(payload_buf_alloc_len), K_(payload_buffered_total_len), K(len), K(ret));
|
||||
SERVER_LOG(ERROR, "invalid buf len", K_(payload_buf_alloc_len),
|
||||
K_(payload_buffered_total_len), K(len), K(ret));
|
||||
} else {
|
||||
MEMCPY(payload_buf_ + payload_buffered_total_len_, start, len);
|
||||
payload_buffered_total_len_ += len;
|
||||
@ -571,5 +587,53 @@ int ObMysqlPktContext::save_fragment_mysql_packet(const char* start, const int64
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // end of namespace obmysql
|
||||
} // end of namespace oceanbase
|
||||
int ObMySQLRequestUtils::flush_compressed_buffer(bool pkt_has_completed, ObCompressionContext &comp_context,
|
||||
ObEasyBuffer &orig_send_buf, rpc::ObRequest &req)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
int64_t need_hold_size = 0;
|
||||
|
||||
if (comp_context.need_hold_last_pkt(pkt_has_completed)) {
|
||||
need_hold_size = orig_send_buf.proxy_read_avail_size(comp_context.last_pkt_pos_);
|
||||
orig_send_buf.write(0 - need_hold_size);
|
||||
SERVER_LOG(DEBUG, "need hold uncompleted proxy pkt", K(need_hold_size),
|
||||
"orig_send_buf", orig_send_buf);
|
||||
}
|
||||
|
||||
if (false == orig_send_buf.is_read_avail()) {
|
||||
|
||||
} else {
|
||||
while (OB_SUCC(ret)
|
||||
&& orig_send_buf.is_read_avail()) {
|
||||
if (OB_FAIL(build_compressed_buffer(orig_send_buf, comp_context))) {
|
||||
SERVER_LOG(WARN, "failed to build_compressed_buffer", K(ret));
|
||||
break;
|
||||
} else if (OB_FAIL(send_compressed_buffer(pkt_has_completed, comp_context, orig_send_buf, req))) {
|
||||
SERVER_LOG(WARN, "faild to send compressed response", K(ret));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (OB_SUCC(ret) && false == pkt_has_completed) {
|
||||
const bool need_reset_last_pkt_pos = (comp_context.last_pkt_pos_ == orig_send_buf.last());
|
||||
init_easy_buf(&orig_send_buf.buf_, reinterpret_cast<char *>(&orig_send_buf.buf_ + 1),
|
||||
NULL, orig_send_buf.orig_buf_size());
|
||||
|
||||
if (need_reset_last_pkt_pos) {
|
||||
if (need_hold_size > 0) {
|
||||
MEMMOVE(orig_send_buf.last(), comp_context.last_pkt_pos_, need_hold_size);
|
||||
orig_send_buf.write(need_hold_size);
|
||||
}
|
||||
comp_context.last_pkt_pos_ = orig_send_buf.begin();
|
||||
SERVER_LOG(DEBUG, "need reset last_pkt_pos", K(need_hold_size),
|
||||
"orig_send_buf_", orig_send_buf,
|
||||
"comp_context", comp_context);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
} //end of namespace obmysql
|
||||
} //end of namespace oceanbase
|
||||
|
||||
Reference in New Issue
Block a user