ats代码有几十万行之多,与请求流程相关的代码主要集中在HttpSM.cc中。文件中包含了三个重要的函数:HttpSM::handle_api_return和HttpSM::set_next_state和HttpSM::call_transact_and_set_next_state,前面两个函数配合实现了状态机的运转,第三个函数是大多数状态要做的事情,并且间接决定了下一个state是什么。

HttpSM::handle_api_return函数是状态机的入口,是一个巨大的switch,每个case是一个state,大多数state最终都会执行到HttpSM::call_transact_and_set_next_state。

这个函数就像其名字一样,做了两件事请:call和set_next_state,call了一个请求在相应state下的处理函数。分两种可能,如果这个函数带了一个参数,参数就是一个函数,就执行这个函数,如果没有带参数,就执行在其他地方设置好的函数。call操作执行的函数一般最后会执行TRANSACT_RETURN函数,这个函数有两个参数,第一个参数是一个state,被赋值于HttpSM::next_action,用于HttpSM::set_next_state中的switch判断,第二个参数是一个函数,被用于下一个state执行是call的函数,也就是说下一次HttpSM::call_transact_and_set_next_state函数的时候如果没有带参数,就会执行上个state的TRANSACT_RETURN函数中第二个参数指向的函数。

根据处理函数的执行情况来执行set_next_state函数,set_next_state函数决定下一个state是什么,可能会直接执行下一个state的HttpSM::call_transact_and_set_next_state也可能回到HttpSM::handle_api_return。

请求第一次进入到HttpSM::handle_api_return时的堆栈信息如下:


Breakpoint 1, HttpSM::handle_api_return (this=0x2ae89f600000) at HttpSM.cc:1580

1580      switch (t_state.api_next_action) {

(gdb) bt

#0  HttpSM::handle_api_return (this=0x2ae89f600000) at HttpSM.cc:1580

#1  0x0000000000596b54 in HttpSM::state_api_callout (this=0x2ae89f600000, event=0, data=0x0) at HttpSM.cc:1541

#2  0x00000000005a23cd in HttpSM::do_api_callout_internal (this=0x2ae89f600000) at HttpSM.cc:4750

#3  0x00000000005afba0 in HttpSM::do_api_callout (this=0x2ae89f600000) at HttpSM.cc:571

#4  0x00000000005936b4 in HttpSM::state_add_to_list (this=0x2ae89f600000, event=0, data=0x0) at HttpSM.cc:599

#5  0x0000000000593d23 in HttpSM::attach_client_session (this=0x2ae89f600000, client_vc=0x2ae89dbe0000, buffer_reader=0x2ae89dbc4018) at HttpSM.cc:705

#6  0x00000000005826f9 in HttpClientSession::new_transaction (this=0x2ae89dbe0000) at HttpClientSession.cc:164

#7  0x0000000000583db3 in HttpClientSession::handle_api_return (this=0x2ae89dbe0000, event=0) at HttpClientSession.cc:535

#8  0x0000000000583cf5 in HttpClientSession::state_api_callout (this=0x2ae89dbe0000, event=0, data=0x0) at HttpClientSession.cc:511

#9  0x00000000005849d6 in HttpClientSession::do_api_callout (this=0x2ae89dbe0000, id=TS_HTTP_SSN_START_HOOK) at HttpClientSession.cc:178

#10 0x0000000000582ab5 in HttpClientSession::new_connection (this=0x2ae89dbe0000, new_vc=0x2ae897f60000, backdoor=false) at HttpClientSession.cc:244

#11 0x000000000057d95b in HttpAcceptCont::mainEvent (this=0x2e8d060, event=202, data=0x2ae897f60000) at HttpAcceptCont.cc:72

#12 0x0000000000508bf8 in Continuation::handleEvent (this=0x2e8d060, event=202, data=0x2ae897f60000) at ../iocore/eventsystem/I_Continuation.h:146

#13 0x0000000000726af2 in ProtocolAcceptCont::mainEvent (this=0x2e8d140, event=202, netvc=0x2ae897f60000) at ProtocolAcceptCont.cc:49

#14 0x0000000000508bf8 in Continuation::handleEvent (this=0x2e8d140, event=202, data=0x2ae897f60000) at ../iocore/eventsystem/I_Continuation.h:146

#15 0x000000000073bc49 in SpdyProberCont::mainEvent (this=0x2ae89dae0000, event=102, e=0x2ae897f60118) at UnixNetVConnection.cc:101

#16 0x0000000000508bf8 in Continuation::handleEvent (this=0x2ae89dae0000, event=102, data=0x2ae897f60118) at ../iocore/eventsystem/I_Continuation.h:146

#17 0x00000000007375dc in read_signal_and_update (event=102, vc=0x2ae897f60000) at UnixNetVConnection.cc:215

#18 0x000000000073778e in read_signal_done (event=102, nh=0x2ae888cdd2c8, vc=0x2ae897f60000) at UnixNetVConnection.cc:245

#19 0x0000000000737f34 in read_from_net (nh=0x2ae888cdd2c8, vc=0x2ae897f60000, thread=0x2ae888cda010) at UnixNetVConnection.cc:397

#20 0x000000000073a0a3 in UnixNetVConnection::net_read_io (this=0x2ae897f60000, nh=0x2ae888cdd2c8, lthread=0x2ae888cda010) at UnixNetVConnection.cc:944

#21 0x00000000007341f0 in NetHandler::mainNetEvent (this=0x2ae888cdd2c8, event=5, e=0x2ae8899ec5c0) at UnixNet.cc:372

#22 0x0000000000508bf8 in Continuation::handleEvent (this=0x2ae888cdd2c8, event=5, data=0x2ae8899ec5c0) at ../iocore/eventsystem/I_Continuation.h:146

#23 0x0000000000761d88 in EThread::process_event (this=0x2ae888cda010, e=0x2ae8899ec5c0, calling_code=5) at UnixEThread.cc:142

#24 0x000000000076235d in EThread::execute (this=0x2ae888cda010) at UnixEThread.cc:266

#25 0x0000000000760f36 in spawn_thread_internal (a=0x2cdf5a0) at Thread.cc:88

#26 0x0000003ce7207aa1 in start_thread () from /lib64/libpthread.so.0

#27 0x0000003ce6ee893d in clone () from /lib64/libc.so.6