digraph ft_send { fontname="Helvetica,Arial,sans-serif" node [fontname="Helvetica,Arial,sans-serif"] edge [fontname="Helvetica,Arial,sans-serif"] //layout=fdp //rankdir = LR start; fail [shape=doublecircle]; done [shape=doublecircle]; // peer offline (how) start -> fail [label="peer offline"] subgraph cluster_init { label="Send Init"; style=filled; //color=lightgrey; // if it fails sent_init1 -> sent_init2 [label="send FT_INIT"] // if it fails again sent_init2 -> sent_init3 [label="send FT_INIT"] } start -> sent_init1 [label="send FT_INIT"] // peer offline (how) sent_init1 -> fail [label="peer offline"] // peer offline (how) sent_init2 -> fail [label="peer offline"] // give up after 3. attempt sent_init3 -> fail [label="no ack / peer offline"] // got an ack after an init sent_init1 -> have_data [label="got init_ack"] sent_init2 -> have_data [label="got init_ack"] sent_init3 -> have_data [label="got init_ack"] subgraph cluster_data { label="for each data chunk"; style=filled; //node [style=filled]; have_data -> data_awaiting_ack [label="send FT_DATA"]; data_awaiting_ack -> data_wait_for_all [label="get FT_DATA_ACK"]; data_awaiting_ack -> have_data [label="no FT_DATA_ACK"]; data_wait_for_all; } // fail have_data -> fail [label="peer offline"] data_wait_for_all -> fail [label="peer offline"] data_wait_for_all -> done [label="all chunks acked"]; }