Fix IP cache accounting to avoid idle caches on busy servers. When maintaining the IP cache size, use the number of entries in the cache rather than the number of allocated and not freed MEM_IPCACHE_ENTRY objects. MEM_IPCACHE_ENTRY objects are used outside the cache for DNS queries. If queries leak (or perhaps when there are just a lot of them), the memory-pool-based count overestimates the cache size, sometimes to such a degree that the cache remains nearly empty despite lots of misses. Use memory-pool-based counter to estimate cache size also violates IP cache encapsulation boundaries because it effectively prevents others from using the same memory pool. === modified file 'src/ipcache.cc' --- src/ipcache.cc 2010-05-04 23:06:00 +0000 +++ src/ipcache.cc 2010-09-08 19:59:11 +0000 @@ -162,6 +162,9 @@ extern int _dns_ttl_; #endif +/// \ingroup IPCacheInternal +inline int ipcacheCount() { return ip_table ? ip_table->count : 0; } + int ipcache_entry::age() const { @@ -236,7 +239,7 @@ eventAdd("ipcache_purgelru", ipcache_purgelru, NULL, 10.0, 1); for (m = lru_list.tail; m; m = prev) { - if (memInUse(MEM_IPCACHE_ENTRY) < ipcache_low) + if (ipcacheCount() < ipcache_low) break; prev = m->prev; @@ -920,8 +923,10 @@ dlink_node *m; assert(ip_table != NULL); storeAppendPrintf(sentry, "IP Cache Statistics:\n"); - storeAppendPrintf(sentry, "IPcache Entries: %d\n", + storeAppendPrintf(sentry, "IPcache Entries In Use: %d\n", memInUse(MEM_IPCACHE_ENTRY)); + storeAppendPrintf(sentry, "IPcache Entries Cached: %d\n", + ipcacheCount()); storeAppendPrintf(sentry, "IPcache Requests: %d\n", IpcacheStats.requests); storeAppendPrintf(sentry, "IPcache Hits: %d\n", @@ -1497,7 +1502,7 @@ case IP_ENT: Answer = snmp_var_new_integer(Var->name, Var->name_length, - memInUse(MEM_IPCACHE_ENTRY), + ipcacheCount(), SMI_GAUGE32); break;