

Changes to GossipRouter in 2.8
==============================
Author: Bela Ban


Motivation
----------

The changes are mainly due to logical addresses and shared transport.

TCPGOSSIP currently doesn't work, as the GossipRouter doesn't return logical addresses *and* their associated physical
addresses, but only returns logical addresses (UUIDs) [1].

In TUNNEL, RouterStubs are conceptually associated with a single channel, and cannot process traffic from multiple
channels on top of a shared transport.

[1] https://jira.jboss.org/jira/browse/JGRP-1005
[2] https://jira.jboss.org/jira/browse/JGRP-924


Design overview
---------------

A RouterStub will simply establish a TCP connection with a GossipRouter, but doesn't send the CONNECT message on
socket establishment. This is typically done in init() of TUNNEL (or TCPGOSSIP).

On channel connection, a CONNECT(groupname, logical_addr, logical_name, physical_addresses) is sent to the
GossipRouter.

On a GET-MEMBERS(groupname), the GR returns a list of <logical-addr, logical-name, physical-addresses> elements.

On a ROUTE(groupname, logical_addr, message), the GR pick the single destination (if logical-addr is not null) and
routes the message. If logical_addr is null, then the GR routes the message to all members keyed by groupname.

The GossipRouter maintains the following data structures:

- RoutingTable:
  - A hashmap with groupnames as keys and hashmaps as values
  - The 2nd level hashmaps have logical addresses as keys and ConnectionHandlers as values
  - A ConnectionHandler represent a physical connection to a client. It has a thread listening for messages on the
    input stream, and it also has a list of logical_addrs from which it received CONNECT messages.
  - When the socket in the ConnectionHandler is closed by the peer, we remove all entries associated with all
    logical_addrs of ConnectionHandler from the other data structures.

- AddressMappings:
  - Maintains a hashmap with logical_addrs as keys and the physical_addrs as value
  - This is used to map logical addresses to their physical addresses, and is only used by TCPGOSSIP


Implementation
--------------

RouterStub
----------
- When started, the RouterStub establishes a socket to the GossipRouter's address:port given
- When the connection is closed by the GR, the stub goes into reconnecting mode. When reconnected, it issues
  a notification so registered listeners can send a CONNECT (see below) to the GR again
- When the CONNECT event is received by TUNNEL / TCPGOSSIP, RouterStub.connect() is called with
  - the groupname
  - the logical address
  - the logical name
  - a list of physical addresses (might be null, only used by TCPGOSSIP)
- This generates a CONNECT message which is sent to the GossipRouter


GossipRouter
------------

- On accept():
  - Create a new ConnectionHandler on a new thread (from the thread pool)
  - This stores the client socket, input and output stream, then listens on the input stream
  [- We might add the ConnectionHandler to a separate list, just to keep track of open connections]

- On peer (RouterStub) closing the socket:
  - The ConnectionHandler gets an exception when listening on the input stream
  - We remove the entries in connection-list from all tables

- On CONNECT(groupname, logical_addr, logical_name, physical_addrs) [received by ConnectionHandler.run()]:
  - The ConnectionHandler adds the logical address to its connection-list
  - An entry is added to RoutingTable under groupname, and the value (hashmap) is updated:
    - key is the logical addr, value the ConnectionHandler (this)
  - If CONNECT ships with non-null physical_addrs, then an entry is added to AddressMappings


- On DISCONNECT(logical_addr):
  - Remove the entry for logical_addr from all tables (RoutingTable, AddressMappings)
  - Do *not* close the socket in ConnectionHandler: others may still be connected through the same connection !


- On GET_MEMBERS(groupname):
  - Grabs the members for groupname (from RoutingTable and AddressMappings) and passes them back, for each member:
    - The logical address
    - The logical name
    - (if available) a list of physical addresses

- On ROUTE(groupname, dest, message):
  - If dest == null (multicast):
    - Grab all ConnectionHandler's from RoutingTable for groupname and send the message to all
  - Else (unicast)
    - Find the ConnectionHandler keyed by 'dest' and send the message to it

TUNNEL
------

- On stub reconnect:
  - Send a CONNECT message. With a shared transort, this has to be done for all channels sharing the transport