nsresult nsMemoryCacheDevice::DeactivateEntry(nsCacheEntry * entry) { CACHE_LOG_DEBUG(("nsMemoryCacheDevice::DeactivateEntry for entry 0x%p\n", entry)); if (entry->IsDoomed()) { #ifdef DEBUG // XXX verify we've removed it from mMemCacheEntries & eviction list #endif delete entry; CACHE_LOG_DEBUG(("deleted doomed entry 0x%p\n", entry)); return NS_OK; } #ifdef DEBUG nsCacheEntry * ourEntry = mMemCacheEntries.GetEntry(entry->Key()); NS_ASSERTION(ourEntry, "DeactivateEntry called for an entry we don't have!"); NS_ASSERTION(entry == ourEntry, "entry doesn't match ourEntry"); if (ourEntry != entry) return NS_ERROR_INVALID_POINTER; #endif mInactiveSize += entry->DataSize(); EvictEntriesIfNecessary(); return NS_OK; }
NS_INTERFACE_MAP_END_THREADSAFE nsresult nsCacheEntryDescriptor:: nsInputStreamWrapper::LazyInit() { // Check if we have the descriptor. If not we can't even grab the cache // lock since it is not ensured that the cache service still exists. if (!mDescriptor) return NS_ERROR_NOT_AVAILABLE; nsCacheServiceAutoLock lock(LOCK_TELEM(NSINPUTSTREAMWRAPPER_LAZYINIT)); nsCacheAccessMode mode; nsresult rv = mDescriptor->GetAccessGranted(&mode); if (NS_FAILED(rv)) return rv; NS_ENSURE_TRUE(mode & nsICache::ACCESS_READ, NS_ERROR_UNEXPECTED); nsCacheEntry* cacheEntry = mDescriptor->CacheEntry(); if (!cacheEntry) return NS_ERROR_NOT_AVAILABLE; rv = nsCacheService::OpenInputStreamForEntry(cacheEntry, mode, mStartOffset, getter_AddRefs(mInput)); CACHE_LOG_DEBUG(("nsInputStreamWrapper::LazyInit " "[entry=%p, wrapper=%p, mInput=%p, rv=%d]", mDescriptor, this, mInput.get(), int(rv))); if (NS_FAILED(rv)) return rv; mInitialized = true; return NS_OK; }
nsresult nsCacheEntryDescriptor:: nsInputStreamWrapper::LazyInit() { nsCacheServiceAutoLock lock(LOCK_TELEM(NSINPUTSTREAMWRAPPER_LAZYINIT)); nsCacheAccessMode mode; nsresult rv = mDescriptor->GetAccessGranted(&mode); if (NS_FAILED(rv)) return rv; NS_ENSURE_TRUE(mode & nsICache::ACCESS_READ, NS_ERROR_UNEXPECTED); nsCacheEntry* cacheEntry = mDescriptor->CacheEntry(); if (!cacheEntry) return NS_ERROR_NOT_AVAILABLE; rv = nsCacheService::OpenInputStreamForEntry(cacheEntry, mode, mStartOffset, getter_AddRefs(mInput)); CACHE_LOG_DEBUG(("nsInputStreamWrapper::LazyInit " "[entry=%p, wrapper=%p, mInput=%p, rv=%d]", mDescriptor, this, mInput.get(), int(rv))); if (NS_FAILED(rv)) return rv; mInitialized = true; return NS_OK; }
bool nsMemoryCacheDevice::EntryIsTooBig(int64_t entrySize) { CACHE_LOG_DEBUG(("nsMemoryCacheDevice::EntryIsTooBig " "[size=%d max=%d soft=%d]\n", entrySize, mMaxEntrySize, mSoftLimit)); if (mMaxEntrySize == -1) return entrySize > mSoftLimit; else return (entrySize > mSoftLimit || entrySize > mMaxEntrySize); }
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); }
nsresult nsCacheEntryDescriptor:: nsInputStreamWrapper::Read_Locked(char *buf, uint32_t count, uint32_t *countRead) { nsresult rv = EnsureInit(); if (NS_SUCCEEDED(rv)) rv = mInput->Read(buf, count, countRead); CACHE_LOG_DEBUG(("nsInputStreamWrapper::Read " "[entry=%p, wrapper=%p, mInput=%p, rv=%d]", mDescriptor, this, mInput.get(), rv)); return rv; }
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)); }
void nsMemoryCacheDevice::EvictEntry(nsCacheEntry * entry, bool deleteEntry) { CACHE_LOG_DEBUG(("Evicting entry 0x%p from memory cache, deleting: %d\n", entry, deleteEntry)); // remove entry from our hashtable mMemCacheEntries.RemoveEntry(entry); // remove entry from the eviction list PR_REMOVE_AND_INIT_LINK(entry); // update statistics int32_t memoryRecovered = (int32_t)entry->DataSize(); mTotalSize -= memoryRecovered; if (!entry->IsDoomed()) mInactiveSize -= memoryRecovered; --mEntryCount; if (deleteEntry) delete entry; }
nsresult nsCacheEntry::CreateDescriptor(nsCacheRequest * request, nsCacheAccessMode accessGranted, nsICacheEntryDescriptor ** result) { NS_ENSURE_ARG_POINTER(request && result); nsCacheEntryDescriptor * descriptor = new nsCacheEntryDescriptor(this, accessGranted); // XXX check request is on q PR_REMOVE_AND_INIT_LINK(request); // remove request regardless of success if (descriptor == nsnull) return NS_ERROR_OUT_OF_MEMORY; PR_APPEND_LINK(descriptor, &mDescriptorQ); CACHE_LOG_DEBUG((" descriptor %p created for request %p on entry %p\n", descriptor, request, this)); NS_ADDREF(*result = descriptor); return NS_OK; }