java.lang.Object
net.i2p.data.i2cp.I2CPMessageReader
net.i2p.internal.QueuedI2CPMessageReader

public class QueuedI2CPMessageReaderextends I2CPMessageReader
Fetches messages off an In-JVM queue, zero-copy. Uses a shared dispatcher pool instead of one thread per instance.
  • Field Details

    • in

      private final I2CPMessageQueue in
      The queue messages are read from.
    • registered

      private volatile boolean registered
      True while the reader is registered with the dispatcher.
    • _claimed

      private final AtomicBoolean _claimed
      Set while a worker is serving this reader.

      I2CP messages for one session are order-dependent, so exactly one worker may touch a reader at a time. Correctness would otherwise rest on the ready queue never holding two entries for the same reader. Claiming it before serving turns that into something the code enforces rather than something registration order has to uphold.

    • DISPATCHER

      private static final QueuedI2CPMessageReader.InternalI2CPDispatcher DISPATCHER
      The shared dispatcher feeding all the readers.
    • MAX_DRAIN_PER_PASS

      static final int MAX_DRAIN_PER_PASS
      Messages one worker takes from a reader before requeueing it.
      See Also:
  • Constructor Details

    • QueuedI2CPMessageReader

      public QueuedI2CPMessageReader(I2CPMessageQueue in, I2CPMessageReader.I2CPMessageEventListener lsnr)
      Creates a new instance of this QueuedMessageReader and registers with the shared dispatcher. Call startReading() to begin.
      Parameters:
      in - the in-JVM queue holding this session's incoming messages
      lsnr - notified with each message as it is dequeued for this session
  • Method Details

    • startReading

      public void startReading()
      Register with the shared dispatcher. Idempotent: a second call must not put a duplicate entry in the ready queue, which would let two workers serve this reader concurrently and deliver its messages out of order.
      Overrides:
      startReading in class I2CPMessageReader
    • stopReading

      public void stopReading()
      Unregister from the shared dispatcher.
      Overrides:
      stopReading in class I2CPMessageReader
    • processOnce

      boolean processOnce()
      Non-blocking poll + dispatch. Called by a dispatcher worker.
      Returns:
      true if a message was processed
    • drainOnce

      int drainOnce(int maxMessages)
      Drain at most maxMessages, then return even if the queue is not empty.

      The bound is what stops one backed-up client from starving every other in-JVM client. Workers are pooled, so a reader that only returns once its queue is empty lets a payload flood hold a worker indefinitely while unrelated clients' queues back up until the router refuses to send to them at all. A full return value means more may be waiting, and the caller requeues the reader to continue.

      Parameters:
      maxMessages - most messages to handle in this call
      Returns:
      messages handled; equal to maxMessages when the queue was not drained
    • claim

      private boolean claim()
      Take exclusive ownership of this reader for the calling worker.
      Returns:
      false when another worker already owns it, or it stopped reading
    • release

      private boolean release()
      Give up ownership after a pass.

      Reports only that the reader is still registered, which is not the same as having more to send: the dispatcher decides what to reoffer from the pass result and needsService().

      Returns:
      true when the reader is still reading
    • needsService

      boolean needsService()
      Whether this reader is still reading and has messages waiting for a worker.

      This is the question the dispatcher's idle tick asks. It is deliberately not the same as release(): release reports only that the reader is still registered, which says nothing about whether its queue holds anything.

      Returns:
      true when a worker should serve this reader now
    • describe

      String describe()
      Name for diagnostics; identifies the session without depending on its internals.
      Returns:
      the listener class name (or "none") and this reader's identity hash