Caches failed lookup attempts to prevent repeated queries to unavailable or malicious peers. Uses per-entry TTL with backoff instead of a wholesale counter wipe: a key that trips the threshold stays cached for entryTtl(tripGeneration) from its last fail, and re-trips extend that hold up to ENTRY_TTL_MAX_MS. Clearing all keys on a timer synchronized re-probe storms across every recently-failed destination at once.
Partial (below-threshold) fail streaks still expire after netdb.negativeCache.cleanupInterval so the historical contract "N fails within the cleaner window" is preserved per key, without resetting unrelated keys.
Thread-safe implementation with atomic counters and scheduled cleanup operations for reliable concurrent access in multi-threaded environments.
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionprivate classTimer event expiring the cached lookups.Field Summary
FieldsModifier and TypeFieldDescriptionprivate final RouterContextThe router context.private final intFailed lookups before a destination is bad.private final intTimed out lookups before a destination is bad.private final Map<Hash, Destination> The destinations known to be bad.Epoch ms until which a tripped key remains negatively cached.private static final longDefault interval between the cleanup runs.private final SimpleTimer2.TimedEventTimer event expiring the cached entries.private final longInterval between the cleanup runs.private final ObjectCounter<Hash> Failed lookups per hash.(package private) static final longFirst-trip hold once the threshold is crossed (ms).(package private) static final longCap on entry TTL after backoff (ms).private final longBase lifetime of a cached entry.private final longLongest lifetime of a cached entry.Last time a fail was recorded for the key (streak / age tracking).private static final intMost bad destinations remembered.(package private) static final intMaximum failures before caching (definitive peer replies, zero-lease).(package private) static final intPure-timeout failures trip at a higher bar so a brief outage doesn't lock a live key.private static final intBackoff shift per trip generation before hitting the cap (2^n).private final ObjectCounter<Hash> Timed out lookups per hash.How many times the key has tripped the threshold (TTL backoff).Constructor Summary
ConstructorsMethod Summary
Modifier and TypeMethodDescriptionvoidNegative cache the hash for one entry-TTL generation.voidclear()Clears the negative cache and bad destinations.voidClears the transient failure count for the given hash only, including its trip generation (next trip starts at base TTL).(package private) static booleancountsAsDefinitiveFail(int peersQueried) Pure decision: does this failure count toward the strict threshold? Zero-peer failures are local (job drop, no tunnels) and must not poison the key.(package private) static longentryTtlMs(int tripGeneration) Pure decision: TTL for a key that has tripped the thresholdtripGenerationtimes (1 = first trip).private voidIf the key already has a per-entry TTL, drop counts when due (lazy expire).voidfailPermanently(Destination dest) Negative cache the hash permanently until restart, but cache the destination.getBadDest(Hash h) Cached bad destination for the given hash.booleanCheck if the hash is in the negative cache.(package private) static booleanisEntryExpired(long cachedUntil, long now) Pure decision: has a tripped entry's TTL expired?(package private) static booleanisStreakStale(long lastFailAt, long now, long streakWindowMs) Pure decision: has a below-threshold fail streak gone stale?private booleanWhether the cache is full enough to stop storing.voidlookupFailed(Hash h) Record a failed lookup for the given hash.voidRecord a pure-timeout search failure (no peer ever replied).private voidOn the transition into the cached state, set a per-entry TTL with backoff from how many times this key has tripped before.private voidrefreshStreak(Hash h, long now) Discard a below-threshold fail streak that has outlivedcleanTimeso "N fails within the window" still holds without a global wipe.voidstop()Stops the timer.
Field Details
counter
Failed lookups per hash.timeoutCounter
Timed out lookups per hash.badDests
The destinations known to be bad.lastFailAt
cachedUntil
tripCount
_maxFails
private final int _maxFailsFailed lookups before a destination is bad._maxTimeoutFails
private final int _maxTimeoutFailsTimed out lookups before a destination is bad.cleaner
Timer event expiring the cached entries.cleanTime
private final long cleanTimeInterval between the cleanup runs.entryTtlBase
private final long entryTtlBaseBase lifetime of a cached entry.entryTtlMax
private final long entryTtlMaxLongest lifetime of a cached entry._context
The router context.MAX_FAILS
static final int MAX_FAILSMaximum failures before caching (definitive peer replies, zero-lease).- See Also:
MAX_TIMEOUT_FAILS
static final int MAX_TIMEOUT_FAILSPure-timeout failures trip at a higher bar so a brief outage doesn't lock a live key.- See Also:
MAX_BAD_DESTS
private static final int MAX_BAD_DESTSMost bad destinations remembered.- See Also:
CLEAN_TIME
private static final long CLEAN_TIMEDefault interval between the cleanup runs.- See Also:
ENTRY_TTL_BASE_MS
static final long ENTRY_TTL_BASE_MSFirst-trip hold once the threshold is crossed (ms).- See Also:
ENTRY_TTL_MAX_MS
static final long ENTRY_TTL_MAX_MSCap on entry TTL after backoff (ms).- See Also:
MAX_TTL_SHIFT
private static final int MAX_TTL_SHIFTBackoff shift per trip generation before hitting the cap (2^n).- See Also:
Constructor Details
NegativeLookupCache
Creates a new NegativeLookupCache.- Parameters:
context- the router context
Method Details
entryTtlMs
static long entryTtlMs(int tripGeneration) Pure decision: TTL for a key that has tripped the thresholdtripGenerationtimes (1 = first trip). Doubling backoff, capped atENTRY_TTL_MAX_MS(overridable max applies at call).- Parameters:
tripGeneration- how many times this key has tripped (0 or less treated as 1)- Returns:
- hold time in ms for the first-trip base of 30s
isEntryExpired
static boolean isEntryExpired(long cachedUntil, long now) Pure decision: has a tripped entry's TTL expired?- Parameters:
cachedUntil- epoch ms at which the entry becomes expired (inclusive)now- current epoch ms- Returns:
- true if the entry should be expired
isStreakStale
static boolean isStreakStale(long lastFailAt, long now, long streakWindowMs) Pure decision: has a below-threshold fail streak gone stale?- Parameters:
lastFailAt- epoch ms of the last fail for the key, or -1 if nonenow- current epoch msstreakWindowMs- how long a partial streak remains valid (age >= window marks stale)- Returns:
- true if partial counts should be discarded
lookupFailed
Record a failed lookup for the given hash. Counts toward the strict threshold (definitive peer replies).- Parameters:
h- the hash that failed lookup
lookupTimeout
Record a pure-timeout search failure (no peer ever replied). Uses a higher threshold so a brief tunnel outage doesn't lock a live key.- Parameters:
h- the hash that timed out
countsAsDefinitiveFail
static boolean countsAsDefinitiveFail(int peersQueried) Pure decision: does this failure count toward the strict threshold? Zero-peer failures are local (job drop, no tunnels) and must not poison the key.- Parameters:
peersQueried- number of peers actually sent a query- Returns:
- true if the failure should use
lookupFailed(Hash)
cache
Negative cache the hash for one entry-TTL generation.- Parameters:
h- the hash to cache
isCached
Check if the hash is in the negative cache. Lazily expires per-entry TTLs and stale fail streaks.- Parameters:
h- the hash to check- Returns:
- true if the hash is cached
failPermanently
Negative cache the hash permanently until restart, but cache the destination.- Parameters:
dest- the destination to permanently fail
getBadDest
Cached bad destination for the given hash.- Parameters:
h- the hash to look up- Returns:
- the destination or null if not cached
clear
Clears the transient failure count for the given hash only, including its trip generation (next trip starts at base TTL). Permanent negative entries (failPermanently(Destination)) are left intact, so a confirmed-bad destination cannot be re-probed into searching.- Parameters:
h- the hash to clear
clear
public void clear()Clears the negative cache and bad destinations.stop
public void stop()Stops the timer. May not be restarted.isTripped
Whether the cache is full enough to stop storing.- Parameters:
h- the key whose fail counters are compared with the thresholds- Returns:
- true if either counter is at or over its cache threshold.
expireDue
refreshStreak
Discard a below-threshold fail streak that has outlivedcleanTimeso "N fails within the window" still holds without a global wipe.- Parameters:
h- the key whose fail streak may have gone stalenow- the current time in epoch milliseconds
maybeTrip
On the transition into the cached state, set a per-entry TTL with backoff from how many times this key has tripped before.- Parameters:
h- the key that may be entering the cached statenow- the current time in epoch milliseconds, the base of the new TTLwasTripped- true if the key was already tripped, in which case nothing changes