digraph SMPAgent {
  graph [fontname=arial]
  node [fontname=arial fontsize=11 shape=box]
  edge [fontname=arial fontsize=10 arrowhead=open arrowtail=open]

  subgraph clusterAgent {
    label="agent threads" 
    main [shape=hexagon color=orange label="main\nthread"]
    aSock [label="user agent TCP socket" color=darkgreen]
    subgraph clusterThreads {
      label="" 
      node [shape=hexagon color=orange]
      runUser [label="runUser\nthread"]
      runServer [label="runServer\nthread"]
      msgSubscriber [label="message\nsubscriber\nthread"]
    }
    main -> {runUser runServer} [style=dashed label=race color=orange fontcolor=orange]
    aSock -> runUser [color=darkgreen]

    acInq [shape=larrow label="agent\nserver\ncommands\nTBQueue"]
    acInq -> runServer [color=darkgreen]
    runServer -> amInq [color=darkgreen label="unknown\nconnection\nor\nwrong\nconnection\nstate"]

    amInq [shape=rarrow label="agent\nserver\nmessages\nTBQueue"]
    amInq -> msgSubscriber [color=blue]

    msgSubscriber -> connectionsStore [dir=both]
    runUser -> connectionsStore [dir=both]
    runServer -> connectionsStore [dir=both]

    connectionsStore [shape=cylinder label="duplex\nconnection\nrecords"]
  }

  subgraph clusterUser {
    label="1 group per user connection"
    uSock [label="user connection TCP socket" color=darkgreen]

    subgraph clusterUserThreads {
      graph [fontsize=11]
      label="user threads"
      node [shape=hexagon, color=orange]
      uAgent [label="user"]
      uSnd [label="send"]
    }

    runUser -> uSock [style=dashed label="connect" color=darkgreen fontcolor=darkgreen]
    runUser -> {uAgent uSnd} [style=dashed label=race color=orange fontcolor=orange]

    uOutq [shape=larrow label="send\nTBQueue"]
    uSock -> uAgent [color=darkgreen]
    uAgent -> uOutq [color=darkgreen label="SMAP\ncommand\nsyntax\nerror"]
    uOutq -> uSnd -> uSock [color=darkgreen]

    msgSubscriber -> uOutq [color=blue label="SMAP\nmessages\nand\ncommand\nresponses"]
    uAgent -> acInq [color=darkgreen label="SMAP\nprotocol\ncommand"]
  }

  subgraph clusterServer {
    label="1 group per SMP server connection"
    sSock [label="SMP server connection TCP socket" color=blue]

    subgraph clusterServerThreads {
      graph [fontsize=11]
      label="server threads"
      node [shape=hexagon, color=orange]
      sAgent [label="server"]
      sSnd [label="send"]
    }

    runServer -> {sAgent sSnd} [style=dashed label=race color=orange fontcolor=orange]

    sOutq [shape=larrow label="send\nTBQueue"]
    sSock -> sAgent [color=blue]
    runServer -> sOutq [color=darkgreen label="SMP\nprotocol\ncommand"]
    sOutq -> sSnd -> sSock [color=blue]

    sAgent -> amInq [color=blue label="wrapped\nSMP\nmessages\nand\ncommand\nresponses"]
  }
}
