class ExploratoryPeerSelectorextends TunnelPeerSelector
Pick peers randomly out of the not-failing pool, and put them into a tunnel ordered by XOR distance from a random key.
  • Field Details

    • EPS_ALL_BANNED_STAT

      static final String EPS_ALL_BANNED_STAT
      Counts selections discarded because every candidate was banlisted.

      Exists to keep the discard branch above honest. The change that replaced restoring the banned selection with discarding it was originally justified by a build-capacity figure that no measurement supported, and the branch then recorded 0 occurrences over roughly two hours. Rather than re-assert a benefit, this counter makes the frequency observable so the branch can be re-evaluated on evidence.

      Must be created before use: StatManager.addRateData on an unregistered name silently drops the sample.

      See Also:
    • EPS_STAT_RATES

      private static final long[] EPS_STAT_RATES
      Rate windows kept for the selector's stats.
    • _exploratoryCooldowns

      private final Map<Hash,Long> _exploratoryCooldowns
      Cooldown entries for exploratory selections, recorded when checkTunnel fails. Separate from the shared TunnelPeerSelector._peerCooldowns so exploratory builds cannot pollute the set used by client pools. Only failures are recorded — healthy selections never cooldown peers.
    • _lastAllGhostSelection

      private final ThreadLocal<Set<Hash>> _lastAllGhostSelection
      Peers from the last selection that were all ghosts, handed to the redraw in selectPeers(TunnelPoolSettings).

      A field rather than a return value because the ghost filter sits deep inside selectPeersInternal(TunnelPoolSettings, int, boolean) and the retry belongs beside the existing cooldown retry, in the one method that already sequences attempts. Per-thread: two selections in flight must not exchange the set they were told to avoid.

  • Constructor Details

    • ExploratoryPeerSelector

      public ExploratoryPeerSelector(RouterContext context)
      Creates the selector over the given router context.
      Parameters:
      context - the router context supplying peers and network state
  • Method Details

    • noteAllBannedDiscard

      private static void noteAllBannedDiscard(RouterContext ctx)
      Record a discarded selection, creating the stat on first use.

      StatManager.addRateData silently drops samples for an unregistered name, so creation is not optional here. No "already created" guard is needed because createRequiredRateStat is itself idempotent.

      Parameters:
      ctx - router context; null is ignored
    • selectPeers

      public List<Hash> selectPeers(TunnelPoolSettings settings)
      Returns ENDPOINT FIRST, GATEWAY LAST!!!! In: us .. closest .. middle .. IBGW Out: OBGW .. middle .. closest .. us.
      Specified by:
      selectPeers in class TunnelPeerSelector
      Parameters:
      settings - the tunnel pool settings
      Returns:
      ordered list of Hash objects (one per peer) specifying what order they should appear in a tunnel (ENDPOINT FIRST). This includes the local router in the list. Never null; an empty list means no peers could be selected.
    • selectPeersInternal

      private List<Hash> selectPeersInternal(TunnelPoolSettings settings, int length, boolean includeCooldowns)
      The actual peer selection, shared between the normal path and the cooldown-bypass retry in selectPeers(TunnelPoolSettings).
      Parameters:
      settings - the tunnel pool settings
      length - the desired tunnel length
      includeCooldowns - whether to exclude peers on selection cooldown
      Returns:
      ordered list of Hash objects (ENDPOINT FIRST), or null if no peers are available or checkTunnel fails
    • selectPeersInternal

      private List<Hash> selectPeersInternal(TunnelPoolSettings settings, int length, boolean includeCooldowns, Set<Hash> alsoExclude)
      Select peers, additionally excluding a set the caller has decided on.

      Used for the ghost retry: the client pools exclude peers that turned out to be ghosts and redraw, so exploratory has to be able to do the same rather than restore a selection the peer measurements just rejected.

      Parameters:
      settings - the tunnel pool settings
      length - the desired tunnel length
      includeCooldowns - whether to exclude peers on selection cooldown
      alsoExclude - peers to exclude on top of the usual set, or null
      Returns:
      ordered list of Hash objects (ENDPOINT FIRST), or null if no peers are available or checkTunnel fails
    • getMinNonfailingPct

      private static int getMinNonfailingPct(RouterContext ctx)
      Minimum share of pools that must be building.
      Parameters:
      ctx - the router's context
      Returns:
      the percentage, from the config
    • getMinActivePeersStartup

      private static int getMinActivePeersStartup(RouterContext ctx)
      Minimum active peers before the startup gate lifts.
      Parameters:
      ctx - the router's context
      Returns:
      the count, from the config
    • getMinActivePeers

      private static int getMinActivePeers(RouterContext ctx)
      Minimum active peers for a normal selection.
      Parameters:
      ctx - the router's context
      Returns:
      the count, from the config
    • shouldPickHighCap

      private boolean shouldPickHighCap()
      Should we pick from the high cap pool instead of the larger not failing pool? This should return false most of the time, but if the not-failing pool's build success rate is much worse, return true so that reliability is maintained.
      Returns:
      whether pick high cap
    • getExploratoryFailPercentage

      private int getExploratoryFailPercentage()
      We should really use the difference between the exploratory fail rate and the high capacity fail rate - but we don't have a stat for high cap, so use the fast (== client) fail rate, it should be close if the expl. and client tunnel lengths aren't too different. So calculate the difference between the exploratory fail rate and the client fail rate, normalized to 100: 100 * ((Efail - Cfail) / (100 - Cfail)) Even this isn't the "true" rate for the NonFailingPeers pool, since we are often building exploratory tunnels using the HighCapacity pool.
      Returns:
      the exploratory fail percentage
    • getFailPercentage

      private int getFailPercentage(String t)
      Failure rate of one tunnel type.
      Parameters:
      t - the tunnel type's name
      Returns:
      the failure percentage
    • getEvents

      private int getEvents(String stat, long period)
      Use current + last to get more recent and smoother data.
      Parameters:
      stat - the full stat name, e.g. tunnel.buildExpire
      period - the rate period in milliseconds
      Returns:
      the event count for that period, 0 if the stat or rate is unknown