emigration_send_start
{
...
msg_set_uint32(m, MIG_FIELD_OP, OPERATION_START);
...
uint64_t start_xmit_ms = 0;
//向目标节点发送消息后,等待emig->ctrl_q队列接收到返回的ACK
//如果在1秒钟内,没收到,则继续向目标节点重发;否则循环等待队列
//emig->ctrl_q接收到不同的ACK类型,返回不同结果,外层调用做相应处理
while (true) {
uint64_t now = cf_getms();
if (cf_queue_sz(emig->ctrl_q) == 0 &&
start_xmit_ms + MIGRATE_RETRANSMIT_STARTDONE_MS < now) {
msg_incr_ref(m);
as_fabric_send(emig->dest, m, AS_FABRIC_CHANNEL_CTRL);
start_xmit_ms = now;
}
if (cf_queue_pop(emig->ctrl_q, &op, MIGRATE_RETRANSMIT_STARTDONE_MS) ==
CF_QUEUE_OK) {
switch (op) {
case OPERATION_START_ACK_OK:
as_fabric_msg_put(m);
return EMIG_START_RESULT_OK;
case OPERATION_START_ACK_EAGAIN:
as_fabric_msg_put(m);
return EMIG_START_RESULT_EAGAIN;
case OPERATION_START_ACK_FAIL:
cf_atomic_int_incr(&ns->migrate_tx_partitions_imbalance);
as_fabric_msg_put(m);
return EMIG_START_RESULT_ERROR;
default:
cf_warning(AS_MIGRATE, "unexpected ctrl op %d", op);
break;
}
}
}
...
}
thread:run_fabric_recv->
fabric_connection_process_readable->
fabric_connection_process_msg:
(*g_fabric.msg_cb[m->type])(node, m, g_fabric.msg_udata[m->type]);
m->type;M_TYPE_MIGRATE即该函数是migrate_receive_msg_cb
emig->ctrl_q队列接收ACK是由run_fabric_recv线程处理,即由函数
migrate_receive_msg_cb处理。和迁入消息处理是一个函数。
int
migrate_receive_msg_cb(cf_node src, msg *m, void *udata)
{
uint32_t op;
if (msg_get_uint32(m, MIG_FIELD_OP, &op) != 0) {
...
}
switch (op) {
//--------------------------------------------
// Emigration - handle requests:
//
case OPERATION_MERGE_META:
emigration_handle_meta_batch_request(src, m);
break;
//--------------------------------------------
// 迁入Immigration - handle requests:
//
case OPERATION_START:
immigration_handle_start_request(src, m);
break;
case OPERATION_INSERT:
immigration_handle_insert_request(src, m);
break;
case OPERATION_DONE:
immigration_handle_done_request(src, m);
break;
case OPERATION_ALL_DONE:
immigration_handle_all_done_request(src, m);
break;
//--------------------------------------------
// 迁出Emigration - handle acknowledgments:
//
case OPERATION_INSERT_ACK:
emigration_handle_insert_ack(src, m);
break;
case OPERATION_START_ACK_OK:
case OPERATION_START_ACK_EAGAIN:
case OPERATION_START_ACK_FAIL:
case OPERATION_DONE_ACK:
case OPERATION_ALL_DONE_ACK:
emigration_handle_ctrl_ack(src, m, op);
break;
//--------------------------------------------
// Immigration - handle acknowledgments:
//
case OPERATION_MERGE_META_ACK:
immigration_handle_meta_batch_ack(src, m);
break;
default:
cf_detail(AS_MIGRATE, "received unexpected message op %u", op);
as_fabric_msg_put(m);
break;
}
return 0;
}
这里只分析迁出:
emigration_handle_ctrl_ack:
cf_queue_push(emig->ctrl_q, &op);
emigration_release(emig);
总结:
1、emigration_send_start函数发送OPERATION_START,目标节点接收到后返回
OPERATION_START_ACK_OK
2、本节点run_fabric_recv函数接收到ACK,并将ACK类型push到emig->ctrl_q队列中
3、emigration_send_start函数从emig->ctrl_q队列pop出接收到的ACK后,退出,进入下一步
4、emigrate_tree函数发送迁移的记录消息OPERATION_INSERT
5、目标节点插入完成,回应OPERATION_INSERT_ACK。
6、emigrate_tree迁移完成后,进入下一步emigration_send_done
7、emigration_send_done发送OPERATION_DONE进入循环等待emig->ctrl_q接收相应;
目标节点接收OPERATION_DONE后,发送OPERATION_DONE_ACK,本阶段接收到ACK退出。
迁移完成。
这里只是迁移的流程框架,具体细节需要结合代码仔细分析