nsresult nsMemoryCacheDevice::DoEvictEntries(bool (*matchFn)(nsCacheEntry* entry, void* args), void* args) { nsCacheEntry * entry; for (int i = kQueueCount - 1; i >= 0; --i) { PRCList * elem = PR_LIST_HEAD(&mEvictionList[i]); while (elem != &mEvictionList[i]) { entry = (nsCacheEntry *)elem; elem = PR_NEXT_LINK(elem); if (!matchFn(entry, args)) continue; if (entry->IsInUse()) { nsresult rv = nsCacheService::DoomEntry(entry); if (NS_FAILED(rv)) { CACHE_LOG_WARNING(("memCache->DoEvictEntries() aborted: rv =%x", rv)); return rv; } } else { EvictEntry(entry, DELETE_ENTRY); } } } return NS_OK; }
nsresult nsMemoryCacheDevice::EvictEntries(const char * clientID) { nsCacheEntry * entry; uint32_t prefixLength = (clientID ? strlen(clientID) : 0); for (int i = kQueueCount - 1; i >= 0; --i) { PRCList * elem = PR_LIST_HEAD(&mEvictionList[i]); while (elem != &mEvictionList[i]) { entry = (nsCacheEntry *)elem; elem = PR_NEXT_LINK(elem); const char * key = entry->Key()->get(); if (clientID && nsCRT::strncmp(clientID, key, prefixLength) != 0) continue; if (entry->IsInUse()) { nsresult rv = nsCacheService::DoomEntry(entry); if (NS_FAILED(rv)) { CACHE_LOG_WARNING(("memCache->EvictEntries() aborted: rv =%x", rv)); return rv; } } else { EvictEntry(entry, DELETE_ENTRY); } } } return NS_OK; }
void nsMemoryCacheDevice::DoomEntry(nsCacheEntry * entry) { #ifdef DEBUG // debug code to verify we have entry nsCacheEntry * hashEntry = mMemCacheEntries.GetEntry(entry->Key()); if (!hashEntry) NS_WARNING("no entry for key"); else if (entry != hashEntry) NS_WARNING("entry != hashEntry"); #endif CACHE_LOG_DEBUG(("Dooming entry 0x%p in memory cache\n", entry)); EvictEntry(entry, DO_NOT_DELETE_ENTRY); }
void nsMemoryCacheDevice::EvictEntriesIfNecessary(void) { nsCacheEntry * entry; nsCacheEntry * maxEntry; CACHE_LOG_DEBUG(("EvictEntriesIfNecessary. mTotalSize: %d, mHardLimit: %d," "mInactiveSize: %d, mSoftLimit: %d\n", mTotalSize, mHardLimit, mInactiveSize, mSoftLimit)); if ((mTotalSize < mHardLimit) && (mInactiveSize < mSoftLimit)) return; uint32_t now = SecondsFromPRTime(PR_Now()); uint64_t entryCost = 0; uint64_t maxCost = 0; do { // LRU-SP eviction selection: Check the head of each segment (each // eviction list, kept in LRU order) and select the maximal-cost // entry for eviction. Cost is time-since-accessed * size / nref. maxEntry = 0; for (int i = kQueueCount - 1; i >= 0; --i) { entry = (nsCacheEntry *)PR_LIST_HEAD(&mEvictionList[i]); // If the head of a list is in use, check the next available entry while ((entry != &mEvictionList[i]) && (entry->IsInUse())) { entry = (nsCacheEntry *)PR_NEXT_LINK(entry); } if (entry != &mEvictionList[i]) { entryCost = (uint64_t) (now - entry->LastFetched()) * entry->DataSize() / std::max(1, entry->FetchCount()); if (!maxEntry || (entryCost > maxCost)) { maxEntry = entry; maxCost = entryCost; } } } if (maxEntry) { EvictEntry(maxEntry, DELETE_ENTRY); } else { break; } } while ((mTotalSize >= mHardLimit) || (mInactiveSize >= mSoftLimit)); }