patch 4.0
This commit is contained in:
@ -24,14 +24,26 @@ namespace oceanbase {
|
||||
namespace sql {
|
||||
namespace dtl {
|
||||
|
||||
ObDtlLocalChannel::ObDtlLocalChannel(const uint64_t tenant_id, const uint64_t id, const ObAddr& peer)
|
||||
ObDtlLocalChannel::ObDtlLocalChannel(
|
||||
const uint64_t tenant_id,
|
||||
const uint64_t id,
|
||||
const ObAddr &peer)
|
||||
: ObDtlBasicChannel(tenant_id, id, peer)
|
||||
{}
|
||||
|
||||
ObDtlLocalChannel::ObDtlLocalChannel(
|
||||
const uint64_t tenant_id,
|
||||
const uint64_t id,
|
||||
const ObAddr &peer,
|
||||
const int64_t hash_val)
|
||||
: ObDtlBasicChannel(tenant_id, id, peer, hash_val)
|
||||
{}
|
||||
|
||||
ObDtlLocalChannel::~ObDtlLocalChannel()
|
||||
{
|
||||
destroy();
|
||||
LOG_TRACE("dtl use time", K(times_), K(write_buf_use_time_), K(send_use_time_));
|
||||
LOG_TRACE("dtl use time", K(times_), K(write_buf_use_time_), K(send_use_time_),
|
||||
KP(id_), KP(peer_id_));
|
||||
}
|
||||
|
||||
int ObDtlLocalChannel::init()
|
||||
@ -44,19 +56,21 @@ int ObDtlLocalChannel::init()
|
||||
}
|
||||
|
||||
void ObDtlLocalChannel::destroy()
|
||||
{}
|
||||
{
|
||||
}
|
||||
|
||||
int ObDtlLocalChannel::feedup(ObDtlLinkedBuffer*& linked_buffer)
|
||||
// 共享内存方式
|
||||
int ObDtlLocalChannel::feedup(ObDtlLinkedBuffer *&linked_buffer)
|
||||
{
|
||||
return attach(linked_buffer);
|
||||
}
|
||||
|
||||
// every return path needs to have on_finish
|
||||
int ObDtlLocalChannel::send_shared_message(ObDtlLinkedBuffer*& buf)
|
||||
// 每一条return路径都必须设置on_finish否则后续会卡死
|
||||
int ObDtlLocalChannel::send_shared_message(ObDtlLinkedBuffer *&buf)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
bool is_block = false;
|
||||
ObDtlChannel* chan = nullptr;
|
||||
ObDtlChannel *chan = nullptr;
|
||||
bool is_first = false;
|
||||
bool is_eof = false;
|
||||
if (nullptr == buf) {
|
||||
@ -65,12 +79,16 @@ int ObDtlLocalChannel::send_shared_message(ObDtlLinkedBuffer*& buf)
|
||||
} else {
|
||||
is_first = buf->is_data_msg() && 1 == buf->seq_no();
|
||||
is_eof = buf->is_eof();
|
||||
if (OB_FAIL(DTL.get_channel(peer_id_, chan))) {
|
||||
if (buf->is_data_msg() && buf->use_interm_result()) {
|
||||
if (OB_FAIL(ObDTLIntermResultManager::process_interm_result(buf, peer_id_))) {
|
||||
LOG_WARN("fail to process internal result", K(ret));
|
||||
}
|
||||
} else if (OB_FAIL(DTL.get_channel(peer_id_, chan))) {
|
||||
int tmp_ret = ret;
|
||||
// cache handling during mixed version runnin scenario during online upgrade
|
||||
// 1) new|old -> old: no handling needed
|
||||
// 2) old -> new: is_data_msg is false, same with old logic
|
||||
// 3) new -> new: is_data_msg might be true, codes between new nodes share the same logic
|
||||
// cache版本升级不需要处理,数据发送到receive端大致几种情况:
|
||||
// 1) new|old -> old 无需处理,不涉及到cache问题
|
||||
// 2) old -> new,is_data_msg 为false,和老逻辑一致
|
||||
// 3) new -> new, is_data_msg可能为true,则new版本之间采用blocking逻辑,不影响其他
|
||||
// only buffer data msg
|
||||
ObDtlMsgHeader header;
|
||||
const bool keep_pos = true;
|
||||
@ -80,22 +98,12 @@ int ObDtlLocalChannel::send_shared_message(ObDtlLinkedBuffer*& buf)
|
||||
LOG_TRACE("receive drain cmd, unregister local channel", KP(peer_id_));
|
||||
ret = OB_SUCCESS;
|
||||
tmp_ret = OB_SUCCESS;
|
||||
} else if (buf->is_data_msg() && buf->use_interm_result()) {
|
||||
ret = OB_SUCCESS;
|
||||
if (OB_FAIL(process_interm_result(buf))) {
|
||||
LOG_WARN("fail to process internal result", K(ret));
|
||||
}
|
||||
} else if (buf->is_data_msg() && 1 == buf->seq_no()) {
|
||||
LOG_TRACE("first msg blocked",
|
||||
K(is_block),
|
||||
KP(peer_id_),
|
||||
K(ret),
|
||||
K(buf->tenant_id()),
|
||||
K(buf->seq_no()),
|
||||
K(buf->is_data_msg()),
|
||||
KP(buf));
|
||||
LOG_TRACE("first msg blocked", K(is_block), KP(peer_id_), K(ret),
|
||||
K(buf->tenant_id()), K(buf->seq_no()), K(buf->is_data_msg()), KP(buf),
|
||||
K(buf->is_eof()));
|
||||
bool is_eof = buf->is_eof();
|
||||
if (OB_FAIL(DTL.get_dfc_server().cache(/*buf->tenant_id(), */ peer_id_, buf, true))) {
|
||||
if (OB_FAIL(DTL.get_dfc_server().cache(/*buf->tenant_id(), */peer_id_, buf, true))) {
|
||||
LOG_WARN("get DTL channel fail", KP(peer_id_), "peer", get_peer(), K(ret), K(tmp_ret));
|
||||
} else {
|
||||
// return block after cache first msg
|
||||
@ -108,41 +116,24 @@ int ObDtlLocalChannel::send_shared_message(ObDtlLinkedBuffer*& buf)
|
||||
buf = nullptr;
|
||||
}
|
||||
} else {
|
||||
LOG_TRACE("get DTL channel fail",
|
||||
K(buf->seq_no()),
|
||||
KP(peer_id_),
|
||||
"peer",
|
||||
get_peer(),
|
||||
K(ret),
|
||||
K(tmp_ret),
|
||||
K(buf->is_data_msg()));
|
||||
LOG_TRACE("get DTL channel fail", K(buf->seq_no()), KP(peer_id_), "peer", get_peer(), K(ret), K(tmp_ret), K(buf->is_data_msg()));
|
||||
}
|
||||
} else {
|
||||
ObDtlLocalChannel* local_chan = reinterpret_cast<ObDtlLocalChannel*>(chan);
|
||||
ObDtlLocalChannel *local_chan = reinterpret_cast<ObDtlLocalChannel*>(chan);
|
||||
if (OB_FAIL(local_chan->feedup(buf))) {
|
||||
LOG_WARN("feed up DTL channel fail", KP(peer_id_), "peer", get_peer(), K(ret));
|
||||
} else if (OB_ISNULL(local_chan->get_dfc())) {
|
||||
LOG_TRACE("dfc of rpc channel is null",
|
||||
K(msg_response_.is_block()),
|
||||
KP(peer_id_),
|
||||
K(ret),
|
||||
KP(local_chan->get_id()),
|
||||
K(local_chan->get_peer()));
|
||||
LOG_TRACE("dfc of rpc channel is null", K(msg_response_.is_block()), KP(peer_id_), K(ret), KP(local_chan->get_id()), K(local_chan->get_peer()));
|
||||
} else if (local_chan->belong_to_receive_data()) {
|
||||
// 必须是receive端,才可以主动回包让transmit端block
|
||||
is_block = local_chan->get_dfc()->is_block(local_chan);
|
||||
LOG_TRACE("need blocking",
|
||||
K(msg_response_.is_block()),
|
||||
KP(peer_id_),
|
||||
K(ret),
|
||||
KP(local_chan->get_id()),
|
||||
K(local_chan->get_peer()),
|
||||
K(local_chan->belong_to_receive_data()),
|
||||
K(local_chan->get_processed_buffer_cnt()),
|
||||
K(local_chan->get_recv_buffer_cnt()));
|
||||
LOG_TRACE("need blocking", K(msg_response_.is_block()), KP(peer_id_), K(ret), KP(local_chan->get_id()),
|
||||
K(local_chan->get_peer()), K(local_chan->belong_to_receive_data()), K(local_chan->get_processed_buffer_cnt()), K(local_chan->get_recv_buffer_cnt()));
|
||||
}
|
||||
DTL.release_channel(local_chan);
|
||||
}
|
||||
if (nullptr == buf) {
|
||||
// 成功attach后,认为申请成功了,由于申请动作由自己申请,但释放权交给了另外一个channel,所以这里假设也是自己申请的,方便统计申请与释放一致
|
||||
free_buffer_count();
|
||||
}
|
||||
}
|
||||
@ -154,11 +145,12 @@ int ObDtlLocalChannel::send_shared_message(ObDtlLinkedBuffer*& buf)
|
||||
metric_.mark_last_out();
|
||||
}
|
||||
}
|
||||
//统一返回消息
|
||||
msg_response_.on_finish(is_block, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObDtlLocalChannel::send_message(ObDtlLinkedBuffer*& buf)
|
||||
int ObDtlLocalChannel::send_message(ObDtlLinkedBuffer *&buf)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (!is_inited_) {
|
||||
@ -175,7 +167,8 @@ int ObDtlLocalChannel::send_message(ObDtlLinkedBuffer*& buf)
|
||||
LOG_WARN("failed to block data flow", K(ret));
|
||||
}
|
||||
}
|
||||
LOG_TRACE("local channel send message", KP(get_id()), K_(peer), K(ret), K(get_send_buffer_cnt()));
|
||||
LOG_TRACE("local channel send message", KP(get_id()), K_(peer), K(ret),
|
||||
K(get_send_buffer_cnt()), K(get_msg_seq_no()));
|
||||
|
||||
if (OB_SUCC(ret) && (!is_drain() || buf->is_eof())) {
|
||||
// The peer may not setup when the first message arrive,
|
||||
@ -208,65 +201,6 @@ int ObDtlLocalChannel::send_message(ObDtlLinkedBuffer*& buf)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObDtlLocalChannel::process_interm_result(ObDtlLinkedBuffer* buffer)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
int64_t channel_id = peer_id_;
|
||||
bool need_free = false;
|
||||
ObDTLIntermResultKey key;
|
||||
ObDTLIntermResultInfo result_info;
|
||||
key.channel_id_ = channel_id;
|
||||
if (OB_ISNULL(buffer)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("fail to process buffer", K(ret));
|
||||
} else if (FALSE_IT(key.time_us_ = buffer->timeout_ts())) {
|
||||
} else if (OB_FAIL(ObDTLIntermResultManager::getInstance().get_interm_result_info(key, result_info))) {
|
||||
if (OB_HASH_NOT_EXIST == ret) {
|
||||
ObMemAttr attr(buffer->tenant_id(), "DtlIntermRes", common::ObCtxIds::WORK_AREA);
|
||||
key.start_time_ = oceanbase::common::ObTimeUtility::current_time();
|
||||
ret = OB_SUCCESS;
|
||||
result_info.is_datum_ = PX_DATUM_ROW == buffer->msg_type();
|
||||
if (OB_FAIL(ObDTLIntermResultManager::getInstance().create_interm_result_info(attr, result_info))) {
|
||||
LOG_WARN("fail to create chunk row store", K(ret));
|
||||
} else if (OB_FAIL(DTL_IR_STORE_DO(
|
||||
result_info, init, 0, buffer->tenant_id(), common::ObCtxIds::WORK_AREA, "DtlIntermRes"))) {
|
||||
LOG_WARN("fail to init buffer", K(ret));
|
||||
} else if (OB_FAIL(ObDTLIntermResultManager::getInstance().insert_interm_result_info(key, result_info))) {
|
||||
LOG_WARN("fail to insert row store", K(ret));
|
||||
}
|
||||
need_free = true;
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
if (!result_info.is_store_valid()) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("fail to get row store", K(ret));
|
||||
} else {
|
||||
ObAtomicAppendBlockCall call(buffer->buf(), buffer->size());
|
||||
if (OB_FAIL(ObDTLIntermResultManager::getInstance().atomic_append_block(key, call))) {
|
||||
LOG_WARN("fail to append block", K(ret));
|
||||
} else {
|
||||
ret = call.ret_;
|
||||
if (OB_SUCCESS != ret) {
|
||||
LOG_WARN("fail to append block", K(ret));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (OB_FAIL(ret) && need_free) {
|
||||
int tmp_ret = OB_SUCCESS;
|
||||
// there won't be a concurrency issue here as it is a point to point serial transmition within
|
||||
// a channel
|
||||
if (OB_SUCCESS != (tmp_ret = ObDTLIntermResultManager::getInstance().erase_interm_result_info(key))) {
|
||||
ObDTLIntermResultManager::getInstance().free_interm_result_info(result_info);
|
||||
} else {
|
||||
// in hash table, erase will clean up the memory
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
} // namespace dtl
|
||||
} // namespace sql
|
||||
} // namespace oceanbase
|
||||
} // dtl
|
||||
} // sql
|
||||
} // oceanbase
|
||||
|
||||
Reference in New Issue
Block a user