GENERAL NOTES ===================================================================== FAQ ===================================================================== 1. Q: where is the server accept loop, and what causes the loop to exit? A. the accept loop is etch_tcpsvr_acceptproc(). destroy_etch_listener() forces the main listener thread down via etch_tcpsvr_close(svr); in destroy_etch_listener. 2. Q. how do we message the accept? A. i_sessionlistener->transport_control. 3. a. the specific transport's (tcpserver's) "session" interface is the i_sessionlistener. b. the i_sessionlistener.thisx is be the etch_tcpserver. c. and the i_sessionlistener.transport is how we message the main listener. d. session.mainlistener is the i_sessionlistener. 4. Q: where is server shutdown recognized? A: etch_tcpserver_listenerproc(), is_shutdown_request = TRUE; svr->is_started = FALSE; and BREAK out of receive loop. 5. Q. where do we catch server's main listener exit? A. xxxx_helper: xxxx_listener_start(); etchlog ("main listener exited\n"); A. etch_tcpserver: etch_tcpserver_listenerproc(); catch result of transport_control(STOP 6. Q. where is server's receive thread recognized? A. etch_tcpsvr_acceptproc() 7. Q. how is the server receive thread object accessed in the generic transport context? A. params.session[i].cx.thread 8. Q. how could we programmatically stop the server main listener from the server's main thread? A. listener->transport_control (listener->thisx, STOP_WAITDOWN, ms); 9. Q. where is the receive loop (data from other side)? A. tcpserver: at etch_tcpserver_listenerproc; line: etch_tcpclient_receive(); tcpconxn: at etch_tcpclient_receivex; line: apr_socket_recv() 10. Q. how is data received off the socket routed? A. etcpconxn: at etch_tcpclient_receivex; line: cx->on_data (tcpx, 0, datalen, buf); 11. Q. where are the tcp connection, packetizer, messagizer, mailbox manager, and delivery service instantiated? A. etch_transport: new_tcp_delivery_service() 12. Q. how is the inter-layer messaging chain constructed? A. a) each layer implements both a session interface and a transport interface, and hosts a session and a transport interface owned by another layer, its session owned by the adjacent higher layer, its transport owned by the adjacent lower layer. b) each layer's constructor is passed the transport implementation of the next lower layer, and sets its own transport to the passed transport interface. c) each layer implements its own session interface, and its constructor sets the session of the next lower layer, to its own session interface implementation. d) the thisx pointers of the hosted session and transport interfaces, are the layer objects which implemented those interfaces. for example, packetizer.session is the session interface implemented by messagizer, and so messagizer.session.thisx is the messagizer. 13. Q. what is the messaging stack hierarchy? A. as follows, transport messaging traveling down towards zero, session messaging traveling up: 1. tcp connection 2. packetizer 3. messagizer 4. mailbox manager 5. delivery service 6. stub 7. stub user interface 14. Q. where is the client receive thread constructed, and what is the receive procedure? A. etch_tcp_client* new_tcp_client (etch_tcp_connection*), called from etch_tcpclient_start_listener(); the receive proc is etch_tcpclient_listenerproc() 15. Q. where is the tcp client receive listener stopped? A. etch_tcpclient_stop_listener(), called from etch_tcpconx_transport_control(), case CLASSID_CONTROL_STOP. ============================================================ debugger breakpoints to catch significant events on SERVER ============================================================ ### MODULE FUNCTION LINE --- ---------------------- ------------------------------ ------------------------------------------------------------- 1. etch_transport new_etch_listener i_sessionlistener* l = new_sessionlistener_interface 2. xxxx_listener_main _tmain xxxx_listener_start (listener, waitupms); 3. xxxx_helper xxxx_listener_start listener->transport_control (START_WAITUP) 4. etch_tcpserver etch_tcpsvr_acceptproc apr_socket_accept (&newsock, ... 5. xxxx_helper xxxx_listener_start listener->wait_exit (listener); 6. NOW BLOCKING WAITING FOR CONNECTION - SEND CONNECT AND DATA 7. etch_tcpserver etch_tcpsvr_acceptproc newx = new_accepted_tcp_connection (hostname, ... 8. etch_tcpserver etch_tcpsvr_acceptproc tcpserver->on_session_accepted (... 9. etch_transport tcpxfact_session_accepted delivery_service = new_etch_transport_a ( 10. etch_transport tcpxfact_session_accepted delivery_service->itm->transport_control (START 11. etch_tcpserver etch_tcpsvr_acceptproc thread = svr->threadpool->run(etch_tcpserver_listenerproc 12a. etch_tcpserver etch_tcpserver_listenerproc mainlistener->transport_control (STOP_WAITDOWN 12b. etch_tcpserver etch_tcpserver_listenerproc ETCHOBJ_DESTROY(cx->session); 13. etch_tcpserver etch_tcpsvr_acceptproc return 14. xxxx_helper xxxx_listener_start etchlog ("main listener exited\n"); 15. etch_tcpserver etch_tcpserver_listenerproc catch result of transport_control(STOP_WAITDOWN 16. xxxx_listener_main _tmain ETCHOBJ_DESTROY(listener); 17. SERVER EXE EXITS ===================================================================== debugger breakpoints to catch the most siginificant events on CLIENT ===================================================================== ### MODULE FUNCTION LINE --- ---------------------- ------------------------------ ------------------------------------------------------------- 1. xxxx_helper start_perf_client remote = new_remote_server () 2. xxxx_helper new_remote_server remote_server = new_xxxx_remote_server () 3. xxxx_remote_server new_xxxx_remote_server rs->server_base = new_xxxx_remote_server_base () 4. xxxx_helper new_remote_server myclient = p->new_client (remote_server); 5. xxxx_client_implx init_xxxx_client_impl pc->xxxx_client_base = new_xxxx_client_base (pc); 6. xxxx_helper new_remote_server client_stub = new_perf_client_stub () 7. etch_stub new_stubimpl_init newstub->stub_base = new_stub () 8. xxxx_helper new_remote_server return 9. etch_remote etchremote_start_waitup return thisx->transport_control(START_WAITUP) 10. etch_transport tcpdelsvc_transport_control dstransport->transport_control() 11. etch_tcpconxn etch_tcpconx_start return etch_tcpconx_open () 12 . xxxx_helper start_xxxx_client remote->destroy(remote); 13. xxxx_remote_server destroy_perf_remote_server ETCHOBJ_DESTROY(thisx->remote_base); 14. xxxx_remote_server destroy_perf_remote_server ETCHOBJ_DESTROY(thisx->server_base); 15. xxxx_remote_server destroy_perf_remote_server ETCHOBJ_DESTROY(thisx->client_factory); 14. etch_transport destroy_etch_client_factory ETCHOBJ_DESTROY(((objmask*)thisx->iclient)); 14. etch_transport destroy_etch_client_factory ETCHOBJ_DESTROY(((objmask*)thisx->stub)); 14. etch_transport destroy_etch_client_factory ETCHOBJ_DESTROY(((objmask*)thisx->dsvc)); 15. xxxx_client_main _tmain if (NULL == remote) break; 17. CLIENT EXE EXITS ===================================================================== Notes on message functionality thread execution ===================================================================== 1. The stub's session i/f becomes the delivery's session in the stub base ctor. 2. The delivery's session is typed to SessionMessage. The setSession sets the entire session object, which in this case is a SessionMessage. So setting the delivery's session also sets its SessionMessage method. a. This means we need to override set_session on all objects whose session i/f augments i_session. 3. Therefore, calling session_message on the transport (delivery) invokes the stub's session_message. 4. The stub's session_message expects as a parameter, a message to be "executed", either on a pool thread or inline. 5. stubbase.session_message : inline execute mode a. type.stub_helper().run (delivery*, _obj, whofrom, msg) this translates to: result = stubhelper(stub, delivery, obj, sender, msg); b. stubhelper's are implemented in the xxxx_server_stub, e.g. perf_server_stub. c. the perf_server_stub stubhelper for the type for perf.add() is as follows: static int run (stub, delivery, i_perf_server* perf, whofrom, msg) { etch_message* rmsg = message_get_in_reply_to(msg); etch_int32* x = message_get msg, perfv._mf_x); etch_int32* y = .... etch_int32* addresult = perf->add (perf, x, y); etch_field* key = builtins._mf_result; /* todo: get from perfvf instead, where to get vf? */ result = message_put (rsmg, key, key, addresult); // if result bad, transport an exception result = delivery->itm->transport_message (delivery, whofrom, rmsg); }