Owns all reverse-DNS state that previously lived in CommSystemFacadeImpl: the size-limited in-memory IP-to-hostname cache with persistent file backup, the background lookup executor used by the non-blocking getCanonicalHostName(String) and getLocalHostName(String) lookups, and the periodic cache file writer. The facade retains thin delegation stubs so external callers are unaffected.
The cache is backed by a disk file that is safely read and written using the writer's own snapshot, so a crash mid-write cannot corrupt existing entries. Entries expire in memory after EXPIRE_TIME and are evicted from disk if older than EVICT_THRESHOLD. Cache size is bounded by memory-based limits (see maxCacheSize(boolean, boolean)) with automatic eviction of expired and then oldest entries.
Supports migration from older cache file formats missing timestamps.
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic classCache entry for IP address and hostname mappings.Field Summary
FieldsModifier and TypeFieldDescription(package private) static final intCleanup frequency once the cache is at or over its cap: a full sweep runs on every 1<<CLEANUP_BITS puts that happen while over/at the cap, instead of on every put.(package private) static final intHow many cache entries the map may exceed its cap by before a sweep runs immediately.(package private) static final StringProperty that enables reverse lookups; the single source of truth.Constructor Summary
ConstructorsConstructorDescriptionReverseDnsLookup(RouterContext ctx, GeoIP geoIP) Create the resolver and its background executor.Method Summary
Modifier and TypeMethodDescription(package private) static booleanaccelerateEviction(int size, int maxSize) Whether a full cache should evict entries at an accelerated rate.voidadjustPool(int coreSize) Adjust the running rDNS executor pool sizes.(package private) static booleancacheFileEntryFresh(long ageMs, long evictThresholdMs) Whether an entry read from the persistence file is fresh enough to reuse.static intThe number of entries in the rDNS cache.booleanWhether reverse lookups are enabled.(package private) static booleanentryExpired(long ageMs, long baseExpireMs, boolean isUnknown) Whether a cache entry has outlived its permitted lifetime.(package private) static intexpireHours(boolean has512MB, boolean has1GB) RDNS cache entry lifetime in hours, based on available memory.intReturns rDNS executor active thread count, or 0 if not running.getCanonicalHostName(String ipAddress) Canonical hostname for the given IP address from cache or DNS.getCanonicalHostNameSync(String ipAddress) The canonical host name for the given IP address, resolved synchronously.static intThe rDNS executor core pool size.getLocalHostName(String ipAddress) Fast hostname lookup that never blocks on I/O (MMDB or network).static intThe rDNS executor max pool size.static intThe computed maximum rDNS cache size based on available memory.intReturns rDNS executor total thread count, or 0 if not running.intReturns rDNS executor pending lookup count, or 0 if not running.static StringCache statistics for monitoring.doubleReturns rDNS executor utilization as a ratio (0.0-1.0), orDouble.NaNif not running.(package private) static intmaxCacheSize(boolean has512MB, boolean has1GB) Maximum rDNS cache size, based on available memory.(package private) static booleanneedRdnscacheSweep(int size, int maxSize, int counter) Decide whether a cache insert must run a full-cache cleanup sweep.static StringThe size of the rDNS cache file, in KB.(package private) static ReverseDnsLookup.CacheEntryParse a persisted line back into a cache entry.(package private) static StringSerialize a cache entry for persistence.(package private) static voidLoad the persistence file into the in-memory cache at startup.static voidsetCorePoolSize(int size) The rDNS executor core pool size, bounded 2-8.static voidsetMaxPoolSize(int size) The rDNS executor max pool size, bounded 2-8.voidshutdown()Stop the periodic cache writer and shut down the lookup executor.
Field Details
PROP_ENABLE_REVERSE_LOOKUPS
Property that enables reverse lookups; the single source of truth.- See Also:
MAX_SLACK
static final int MAX_SLACKHow many cache entries the map may exceed its cap by before a sweep runs immediately. Trades a few hundred surplus entries (CHM node wins are negligible) for avoiding a synchronous full-map sweep on every put.- See Also:
CLEANUP_BITS
static final int CLEANUP_BITSCleanup frequency once the cache is at or over its cap: a full sweep runs on every 1<<CLEANUP_BITS puts that happen while over/at the cap, instead of on every put.- See Also:
Constructor Details
ReverseDnsLookup
Create the resolver and its background executor.The executor is started eagerly so the queue-size rate stat is ready before the first lookup, avoiding a first-hit initialization stall on the page-rendering path.
- Parameters:
ctx- the router contextgeoIP- already-constructed GeoIP database for ASN fallback
Method Details
expireHours
static int expireHours(boolean has512MB, boolean has1GB) RDNS cache entry lifetime in hours, based on available memory.Routers with less than 512 MB keep entries for 24 h; routers with at least 1 GB keep them for 48 h; everything else for 36 h. This bounds how stale a cached hostname may be before it is re-resolved, trading freshness against load on small memory-constrained routers.
- Parameters:
has512MB- true if the router has at least 512 MB of max memoryhas1GB- true if the router has at least 1 GB of max memory- Returns:
- entry lifetime in hours (24, 36, or 48)
maxCacheSize
static int maxCacheSize(boolean has512MB, boolean has1GB) Maximum rDNS cache size, based on available memory.Caches 8000 entries on very limited routers, 24000 on routers with at least 1 GB, and 16000 otherwise. The bound prevents the persistence file and the in-memory map from growing without limit on the control path.
- Parameters:
has512MB- true if the router has at least 512 MB of max memoryhas1GB- true if the router has at least 1 GB of max memory- Returns:
- maximum number of cached entries (8000, 16000, or 24000)
accelerateEviction
static boolean accelerateEviction(int size, int maxSize) Whether a full cache should evict entries at an accelerated rate.When the cache exceeds 90% of its maximum size, the TTL applied by
entryExpired(long, long, boolean)is halved so eviction keeps up with insertion load. Choosing the threshold as a percentage of the max (not an absolute number) keeps behavior consistent across the memory-dependent cache sizes.- Parameters:
size- current cache entry countmaxSize- maximum cache entry count- Returns:
- true if the cache is more than 90% full
entryExpired
static boolean entryExpired(long ageMs, long baseExpireMs, boolean isUnknown) Whether a cache entry has outlived its permitted lifetime."unknown" entries (failed lookups) expire after a short fixed window so dead IPs are re-probed; all other entries use the caller-supplied base TTL, which itself may be halved by
accelerateEviction(int, int).- Parameters:
ageMs- age of the entry in millisecondsbaseExpireMs- normal entry TTL in millisecondsisUnknown- true if the cached hostname is the "unknown" marker- Returns:
- true if the entry should be evicted
cacheFileEntryFresh
static boolean cacheFileEntryFresh(long ageMs, long evictThresholdMs) Whether an entry read from the persistence file is fresh enough to reuse.Applies only at startup when the file is loaded. Entries older than the eviction threshold are skipped so a long-idle router does not resurrect months-old hostnames.
- Parameters:
ageMs- age of the entry in millisecondsevictThresholdMs- maximum age accepted at load time- Returns:
- true if the entry is fresh enough to cache
enableReverseLookups
public boolean enableReverseLookups()Whether reverse lookups are enabled.- Returns:
- true if reverse lookups are enabled
getCorePoolSize
public static int getCorePoolSize()The rDNS executor core pool size.- Returns:
- the core pool size, bounded 2-8
setCorePoolSize
public static void setCorePoolSize(int size) The rDNS executor core pool size, bounded 2-8.- Parameters:
size- the new core pool size
getMaxPoolSize
public static int getMaxPoolSize()The rDNS executor max pool size.- Returns:
- the max pool size, bounded 2-8
setMaxPoolSize
public static void setMaxPoolSize(int size) The rDNS executor max pool size, bounded 2-8.- Parameters:
size- the new max pool size
rdnsCacheSize
The size of the rDNS cache file, in KB.- Returns:
- the file size in KB, suffixed with "KB"
countRdnsCacheEntries
public static int countRdnsCacheEntries()The number of entries in the rDNS cache.- Returns:
- the number of cached IP address to host name mappings
getRdnsCacheStats
Cache statistics for monitoring.- Returns:
- formatted string with cache stats
getMaxRdnsCacheSize
public static int getMaxRdnsCacheSize()The computed maximum rDNS cache size based on available memory.- Returns:
- the computed maximum rDNS cache size based on available memory
adjustPool
public void adjustPool(int coreSize) Adjust the running rDNS executor pool sizes. Called by the Tuner when queue depth signals scaling.- Parameters:
coreSize- new core pool size (bounded 2-8)
getQueueSize
public int getQueueSize()Returns rDNS executor pending lookup count, or 0 if not running.- Returns:
- the rdns queue size
getActiveCount
public int getActiveCount()Returns rDNS executor active thread count, or 0 if not running.- Returns:
- the rdns active count
getPoolSize
public int getPoolSize()Returns rDNS executor total thread count, or 0 if not running.- Returns:
- the rdns pool size
getUtilization
public double getUtilization()Returns rDNS executor utilization as a ratio (0.0-1.0), orDouble.NaNif not running.- Returns:
- the rdns utilization
shutdown
public void shutdown()Stop the periodic cache writer and shut down the lookup executor.Cancels the background cache-file timer and the rDNS executor, waiting up to 5 seconds for in-flight lookups to drain before force-interrupting them, and clears the in-flight marker set so a later restart does not inherit stale pending state.
readRDNSCacheFromFile
static void readRDNSCacheFromFile()Load the persistence file into the in-memory cache at startup.Skips "#" comment lines and entries older than the eviction threshold, then schedules the periodic cache-file writer task (
RDNSCacheFileWriter). A missing file is created so the periodic writer always has a valid target. Invoked from the facade once reverse lookups are enabled after the netdb settles.rdnsEntryToString
Serialize a cache entry for persistence.Format is "ip,hostname,timestamp". One line per entry. The timestamp enables expiration and startup filtering, and distinguishes the current format from the two-part legacy format (see
rdnsEntryFromString(String)).- Parameters:
entry- the entry to serialize- Returns:
- the serialized entry line
rdnsEntryFromString
Parse a persisted line back into a cache entry.Three-part lines carry an explicit timestamp. Two-part lines are the pre-timestamp legacy format and are migrated with the current time. Any other shape returns null and the caller skips the line.
- Parameters:
s- the persisted line- Returns:
- the parsed entry, or null if the line is malformed
needRdnscacheSweep
static boolean needRdnscacheSweep(int size, int maxSize, int counter) Decide whether a cache insert must run a full-cache cleanup sweep. SeeneedRdnscacheSweep(int, int, int)for the amortization rule.Sweeping on every put when the cache sits at its cap is O(n) per insert and shows up as CHM iterator churn on the rDNS hot path. Instead the sweep is amortized: once the map is at/over its cap it runs at most once every
CLEANUP_BITSinserts (it usually stays pegged at the cap in steady state), while exceeding the cap by more thanMAX_SLACKentries still sweeps immediately so the memory bound stays hard.A benign race on the shared
_rdnsCleanupCounteronly changes which insert triggers the sweep; it never under-sweeps below the slack guard (the size check is made against the live map by the caller).- Parameters:
size- current cache size; userdnsCache.size()maxSize- the cache cap, e.g.MAX_RDNS_CACHE_SIZEcounter- a per-put counter, e.g. an incrementing static int- Returns:
- true if a cleanup sweep must run before the insert
getCanonicalHostName
Canonical hostname for the given IP address from cache or DNS. If RDNS is enabled, performs a reverse DNS lookup first. Falls back to local ASN database if DNS fails, returning the org name.- Parameters:
ipAddress- IP address to resolve, or null/"null" to return null- Returns:
- hostname, org name from ASN database, or null for invalid input
getCanonicalHostNameSync
getLocalHostName
Fast hostname lookup that never blocks on I/O (MMDB or network). Returns cached result if available and useful. On cache miss, queues a background job that does ASN org name lookup (MMDB file read + regex normalization) and optional RDNS, then returns null immediately — page rendering is never blocked.- Parameters:
ipAddress- the peer IP address to name, a null or literal "null" yields null- Returns:
- cached hostname/ASN org name, or null if not yet resolved