Do not release entries that may be kept in local memory cache. Since r11969, Squid calls trimMemory() for all entries, including non-swappable, to release unused MemObjects memory. But it should not release objects that are or should be stored in local memory cache. StoreEntry::trimMemory() has a check for IN_MEMORY status for that. But IN_MEMORY status is set too late in StoreController::handleIdleEntry(), after trimMemory() marks entry for release: clientReplyContext::removeStoreReference() storeUnregister() StoreEntry::swapOut() StoreEntry::trimMemory() StoreEntry::releaseRequest() StoreEntry::unlock() StoreController::handleIdleEntry() // never get here because entry is set IN_MEMORY status // already marked for release The patch adds another check to StoreEntry::trimMemory() to avoid trimming of entries that may be cached in memory (local or shared). We do not know if the entry would really be cached, the final decision may be complex. So for now we just keep all entries that may be cached, potentially allowing more entries (and hence using more memory) than we could. === modified file 'src/store.cc' --- src/store.cc 2012-01-13 13:49:26 +0000 +++ src/store.cc 2012-07-05 17:07:04 +0000 @@ -1885,40 +1885,50 @@ StoreEntry::getSerialisedMetaData() StoreMeta *tlv_list = storeSwapMetaBuild(this); int swap_hdr_sz; char *result = storeSwapMetaPack(tlv_list, &swap_hdr_sz); storeSwapTLVFree(tlv_list); assert (swap_hdr_sz >= 0); mem_obj->swap_hdr_sz = (size_t) swap_hdr_sz; return result; } void StoreEntry::trimMemory(const bool preserveSwappable) { /* * DPW 2007-05-09 * Bug #1943. We must not let go any data for IN_MEMORY * objects. We have to wait until the mem_status changes. */ if (mem_status == IN_MEMORY) return; + /* + * Do not free data if the entry may be cached in memory (local or + * shared) later. We do not know if the entry would really be + * cached, the final decision may be complex. So for now we just + * keep all entries that may be cached, potentially allowing more + * entries (and hence using more memory) than we could. + */ + if (memoryCachable()) + return; + if (!preserveSwappable) { if (mem_obj->policyLowestOffsetToKeep(0) == 0) { /* Nothing to do */ return; } /* * Its not swap-able, and we're about to delete a chunk, * so we must make it PRIVATE. This is tricky/ugly because * for the most part, we treat swapable == cachable here. */ releaseRequest(); mem_obj->trimUnSwappable (); } else { mem_obj->trimSwappable (); } } bool StoreEntry::modifiedSince(HttpRequest * request) const {