void CacheStorageService::MemoryPool::PurgeByFrecency(bool &aFrecencyNeedsSort, uint32_t aWhat) { MOZ_ASSERT(IsOnManagementThread()); if (aFrecencyNeedsSort) { mFrecencyArray.Sort(FrecencyComparator()); aFrecencyNeedsSort = false; } uint32_t const memoryLimit = Limit(); for (uint32_t i = 0; mMemorySize > memoryLimit && i < mFrecencyArray.Length();) { if (CacheIOThread::YieldAndRerun()) return; nsRefPtr<CacheEntry> entry = mFrecencyArray[i]; if (entry->Purge(aWhat)) { LOG((" abandoned (%d), entry=%p, frecency=%1.10f", aWhat, entry.get(), entry->GetFrecency())); continue; } // not purged, move to the next one ++i; } }
void CacheStorageService::ShutdownBackground() { MOZ_ASSERT(IsOnManagementThread()); mFrecencyArray.Clear(); mExpirationArray.Clear(); }
void CacheStorageService::MemoryPool::PurgeExpired() { MOZ_ASSERT(IsOnManagementThread()); mExpirationArray.Sort(ExpirationComparator()); uint32_t now = NowInSeconds(); uint32_t const memoryLimit = Limit(); for (uint32_t i = 0; mMemorySize > memoryLimit && i < mExpirationArray.Length();) { if (CacheIOThread::YieldAndRerun()) return; nsRefPtr<CacheEntry> entry = mExpirationArray[i]; uint32_t expirationTime = entry->GetExpirationTime(); if (expirationTime > 0 && expirationTime <= now) { LOG((" dooming expired entry=%p, exptime=%u (now=%u)", entry.get(), entry->GetExpirationTime(), now)); entry->PurgeAndDoom(); continue; } // not purged, move to the next one ++i; } }
void CacheStorageService::PurgeOverMemoryLimit() { MOZ_ASSERT(IsOnManagementThread()); LOG(("CacheStorageService::PurgeOverMemoryLimit")); Pool(true).PurgeOverMemoryLimit(); Pool(false).PurgeOverMemoryLimit(); }
void CacheStorageService::RegisterEntry(CacheEntry* aEntry) { MOZ_ASSERT(IsOnManagementThread()); if (mShutdown || !aEntry->CanRegister()) return; LOG(("CacheStorageService::RegisterEntry [entry=%p]", aEntry)); mFrecencyArray.InsertElementSorted(aEntry, FrecencyComparator()); mExpirationArray.InsertElementSorted(aEntry, ExpirationComparator()); aEntry->SetRegistered(true); }
void CacheStorageService::UnregisterEntry(CacheEntry* aEntry) { MOZ_ASSERT(IsOnManagementThread()); if (!aEntry->IsRegistered()) return; LOG(("CacheStorageService::UnregisterEntry [entry=%p]", aEntry)); mozilla::DebugOnly<bool> removedFrecency = mFrecencyArray.RemoveElement(aEntry); mozilla::DebugOnly<bool> removedExpiration = mExpirationArray.RemoveElement(aEntry); MOZ_ASSERT(mShutdown || (removedFrecency && removedExpiration)); // Note: aEntry->CanRegister() since now returns false aEntry->SetRegistered(false); }
void CacheStorageService::PurgeAll(uint32_t aWhat) { LOG(("CacheStorageService::PurgeAll aWhat=%d", aWhat)); MOZ_ASSERT(IsOnManagementThread()); for (uint32_t i = 0; i < mFrecencyArray.Length();) { nsRefPtr<CacheEntry> entry = mFrecencyArray[i]; if (entry->Purge(aWhat)) { LOG((" abandoned entry=%p", entry.get())); continue; } // not purged, move to the next one ++i; } }
void CacheStorageService::PurgeOverMemoryLimit() { MOZ_ASSERT(IsOnManagementThread()); LOG(("CacheStorageService::PurgeOverMemoryLimit")); #ifdef MOZ_LOGGING TimeStamp start(TimeStamp::Now()); #endif uint32_t const memoryLimit = CacheObserver::MemoryLimit(); if (mMemorySize > memoryLimit) { LOG((" memory data consumption over the limit, abandon expired entries")); PurgeExpired(); } bool frecencyNeedsSort = true; if (mMemorySize > memoryLimit) { LOG((" memory data consumption over the limit, abandon disk backed data")); PurgeByFrecency(frecencyNeedsSort, CacheEntry::PURGE_DATA_ONLY_DISK_BACKED); } if (mMemorySize > memoryLimit) { LOG((" metadata consumtion over the limit, abandon disk backed entries")); PurgeByFrecency(frecencyNeedsSort, CacheEntry::PURGE_WHOLE_ONLY_DISK_BACKED); } if (mMemorySize > memoryLimit) { LOG((" memory data consumption over the limit, abandon any entry")); PurgeByFrecency(frecencyNeedsSort, CacheEntry::PURGE_WHOLE); } LOG((" purging took %1.2fms", (TimeStamp::Now() - start).ToMilliseconds())); mPurging = false; }