Class QuicheTripConnectionPool

All Implemented Interfaces:
Pool<Connection>

public class QuicheTripConnectionPool extends AbstractConnectionPool
The QUIC client connection pool.

All pooled connections are streams multiplexed over a single QUIC connection. Since that connection is discarded silently by both peers as soon as it stays idle for longer than the QUIC max idle timeout (see QuicheTripTransport.getMaxIdleSeconds()), which is much shorter than the pool's idle timeout, it is kept alive by sending ack-eliciting packets. Otherwise, the pool would hand out connections belonging to a QUIC connection that is long gone.

Because each pooled connection holds one of the streams the peer allows for the whole time it is in the pool, the pool's maximum size defaults to QuicheTripTransport.getMaxStreams() instead of being unlimited. Should the peer nevertheless grant fewer streams, opening another one fails at once with a temporary TripRuntimeException.

The QUIC connection is established right away when the pool is created, which in turn happens when the transport hands out its first client connection. The server's host name is resolved only then, once for the lifetime of the pool.

The QUIC connection migrates to a new source port when its path stalls (see QuicheTripTransport.getMigrationProbeTimeouts()). If it is lost anyway, it is re-established on a new endpoint, i.e., from a fresh source port as well: the one the lost connection used may well be what got it stuck. That happens when the next connection is requested from the pool, see restoreMinimumSize(int).

A lent connection holds a lease on the QUIC connection (see QuicheConnection.acquire()), since a call is in flight on it. A QUIC connection that cannot migrate any further, because a migration used up the server's spare connection IDs, is therefore given up on as soon as no call is in flight anymore, and replaced with the next get() by one with a full set of connection IDs, before its path stalls again.

  • Field Details

    • DEFAULT_CONNECT_TIMEOUT

      public static final int DEFAULT_CONNECT_TIMEOUT
      The default connect timeout in seconds, applied if the URI does not specify connecttimeout.

      This is the timeout for establishing the QUIC connection, i.e., the handshake with the server, not for the individual streams created per pool slot.

      See Also:
  • Constructor Details

    • QuicheTripConnectionPool

      public QuicheTripConnectionPool(QuicheTripTransport transport, Dictionary dictionary)
      Creates a QUIC connection pool and establishes the QUIC connection.
      Parameters:
      transport - the transport associated with this pool
      dictionary - the dictionary associated with this pool
      Throws:
      IllegalArgumentException - if the URI has no port > 0, or connecttimeout is not > 0
      TripRuntimeException - if a URI parameter is invalid or the QUIC connection cannot be established
  • Method Details

    • shutdown

      public void shutdown()
      Shuts down the pool.
      Closes all resources.

      Deliberately not synchronized: AbstractPool.shutdown() closes the pooled connections without holding the pool's monitor, on purpose, since it waits for each of them. Only accessing the QUIC connection needs the monitor.

      Specified by:
      shutdown in interface Pool<Connection>
      Overrides:
      shutdown in class AbstractPool<Connection>
    • get

      public Connection get()
      Gets a resource from the pool.
      The pool is enlarged if all resources are in use.

      Overridden to take a lease on the QUIC connection for the call the connection is lent for. Not synchronized: the lease is lock-free, and taking the pool's monitor here would serialize all calls.

      Specified by:
      get in interface Pool<Connection>
      Overrides:
      get in class AbstractPool<Connection>
      Returns:
      the resource, never null
    • put

      public void put(Connection connection)
      Returns a resource to the pool.

      Notice: returning a resource more than once is allowed.
      Returning a closed resource removes it from the pool. Returning a resource to a pool that is shut down closes the resource.

      Overridden to release the lease taken by get().

      Specified by:
      put in interface Pool<Connection>
      Overrides:
      put in class AbstractPool<Connection>
      Parameters:
      connection - the resource
    • restoreMinimumSize

      protected void restoreMinimumSize(int num)
      Brings the pool back to its minimum size.

      Invoked by AbstractPool.monitor() with the pool's monitor held, i.e., usually from the PoolTimeoutThread all pools share. The default implementation creates the missing slots. A pool whose resources cannot be created without blocking for long — because they depend on something that is gone and has to be re-established first — should override this and leave the pool below its minimum size instead: AbstractPool.get() creates the resources as soon as they are needed.

      Overridden to do nothing while the QUIC connection is gone. Creating a slot would re-establish it first, which waits for the handshake for as long as connecttimeout allows if the server is not reachable — with the pool's monitor held, on the thread that monitors all pools, and again with every round. The connection is re-established by the next get() instead, i.e., when it is needed.

      Overrides:
      restoreMinimumSize in class AbstractPool<Connection>
      Parameters:
      num - the number of slots missing
    • createSlot

      protected PoolSlot<Connection> createSlot(int slotNumber)
      Description copied from class: AbstractPool
      Creates a new slot.
      Specified by:
      createSlot in class AbstractPool<Connection>
      Parameters:
      slotNumber - the slot number, starting at 0
      Returns:
      the slot
    • connect

      protected void connect()
      Establishes the QUIC connection all pooled connections are multiplexed over.
      A previously established connection is closed first, together with its endpoint: the new connection gets an endpoint of its own, and with it a fresh source port.
    • closeConnection

      protected void closeConnection()
      Closes the QUIC connection if there is one.
      Closing is best effort: the connection may be gone already.