/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
CacheFileContextEvictorEntry* entry = nullptr; if (aLoadContextInfo) { for (uint32_t i = 0; i < mEntries.Length(); ++i) { if (mEntries[i]->mInfo && mEntries[i]->mInfo->Equals(aLoadContextInfo) &&
mEntries[i]->mPinned == aPinned &&
mEntries[i]->mOrigin.Equals(aOrigin)) {
entry = mEntries[i].get(); break;
}
}
} else { // Not providing load context info means we want to delete everything, // so let's not bother with any currently running context cleanups // for the same pinning state. for (uint32_t i = mEntries.Length(); i > 0;) {
--i; if (mEntries[i]->mInfo && mEntries[i]->mPinned == aPinned) {
RemoveEvictInfoFromDisk(mEntries[i]->mInfo, mEntries[i]->mPinned,
mEntries[i]->mOrigin);
mEntries.RemoveElementAt(i);
}
}
}
if (!entry) {
entry = new CacheFileContextEvictorEntry();
entry->mInfo = aLoadContextInfo;
entry->mPinned = aPinned;
entry->mOrigin = aOrigin;
mEntries.AppendElement(WrapUnique(entry));
}
if (mIndexIsUpToDate) { // Already existing context could be added again, in this case the iterator // would be recreated. Close the old iterator explicitely. if (entry->mIterator) {
entry->mIterator->Close();
entry->mIterator = nullptr;
}
rv = CacheIndex::GetIterator(aLoadContextInfo, false,
getter_AddRefs(entry->mIterator)); if (NS_FAILED(rv)) { // This could probably happen during shutdown. Remove the entry from // the array, but leave the info on the disk. No entry can be opened // during shutdown and we'll load the eviction info on next start.
LOG(
("CacheFileContextEvictor::AddContext() - Cannot get an iterator. " "[rv=0x%08" PRIx32 "]", static_cast<uint32_t>(rv)));
mEntries.RemoveElement(entry); return rv;
}
bool isUpToDate = false;
CacheIndex::IsUpToDate(&isUpToDate); if (mEntries.Length() == 0) { // Just save the state and exit, since there is nothing to do
mIndexIsUpToDate = isUpToDate; return;
}
if (!isUpToDate && !mIndexIsUpToDate) { // Index is outdated and status has not changed, nothing to do. return;
}
if (isUpToDate && mIndexIsUpToDate) { // Status has not changed, but make sure the eviction is running. if (mEvicting) { return;
}
// We're not evicting, but we should be evicting?!
LOG(
("CacheFileContextEvictor::CacheIndexStateChanged() - Index is up to " "date, we have some context to evict but eviction is not running! " "Starting now."));
}
// Let's see if we have an origin.
nsAutoCString origin; if (decoded.Contains('\t')) { auto split = decoded.Split('\t');
MOZ_ASSERT(decoded.CountChar('\t') == 1);
nsCOMPtr<nsILoadContextInfo> info; if (!"*"_ns.Equals(decoded)) { // "*" is indication of 'delete all', info left null will pass // to CacheFileContextEvictor::AddContext and clear all the cache data.
info = CacheFileUtils::ParseKey(decoded); if (!info) {
LOG(
("CacheFileContextEvictor::LoadEvictInfoFromDisk() - Cannot parse " "context key, removing file. [contextKey=%s, file=%s]",
decoded.get(), leaf.get()));
file->Remove(false); continue;
}
}
PRTime lastModifiedTime;
rv = file->GetLastModifiedTime(&lastModifiedTime); if (NS_FAILED(rv)) { continue;
}
nsAutoCString keyPrefix; if (aPinned) { // Mark pinned context files with a tab char at the start. // Tab is chosen because it can never be used as a context key tag.
keyPrefix.Append('\t');
} if (aLoadContextInfo) {
CacheFileUtils::AppendKeyPrefix(aLoadContextInfo, keyPrefix);
} else {
keyPrefix.Append('*');
} if (!aOrigin.IsEmpty()) {
keyPrefix.Append('\t');
keyPrefix.Append(NS_ConvertUTF16toUTF8(aOrigin));
}
for (uint32_t i = 0; i < mEntries.Length(); ++i) { if (mEntries[i]->mIterator) {
mEntries[i]->mIterator->Close();
mEntries[i]->mIterator = nullptr;
}
}
}
if (!mIndexIsUpToDate) {
LOG(
("CacheFileContextEvictor::EvictEntries() - Stopping evicting due to " "outdated index.")); return;
}
while (true) { if (CacheObserver::ShuttingDown()) {
LOG(
("CacheFileContextEvictor::EvictEntries() - Stopping evicting due to " "shutdown."));
mEvicting = true; // We don't want to start eviction again during shutdown // process. Setting this flag to true ensures it. return;
}
if (CacheIOThread::YieldAndRerun()) {
LOG(
("CacheFileContextEvictor::EvictEntries() - Breaking loop for higher " "level events."));
mEvicting = true; return;
}
if (mEntries.Length() == 0) {
LOG(
("CacheFileContextEvictor::EvictEntries() - Stopping evicting, there " "is no context to evict."));
// Allow index to notify AsyncGetDiskConsumption callbacks. The size is // actual again.
CacheIndex::OnAsyncEviction(false); return;
}
SHA1Sum::Hash hash;
rv = mEntries[0]->mIterator->GetNextHash(&hash); if (rv == NS_ERROR_NOT_AVAILABLE) {
LOG(
("CacheFileContextEvictor::EvictEntries() - No more entries left in " "iterator. [iterator=%p, info=%p]",
mEntries[0]->mIterator.get(), mEntries[0]->mInfo.get()));
RemoveEvictInfoFromDisk(mEntries[0]->mInfo, mEntries[0]->mPinned,
mEntries[0]->mOrigin);
mEntries.RemoveElementAt(0); continue;
} if (NS_FAILED(rv)) {
LOG(
("CacheFileContextEvictor::EvictEntries() - Iterator failed to " "provide next hash (shutdown?), keeping eviction info on disk." " [iterator=%p, info=%p]",
mEntries[0]->mIterator.get(), mEntries[0]->mInfo.get()));
mEntries.RemoveElementAt(0); continue;
}
RefPtr<CacheFileHandle> handle;
CacheFileIOManager::gInstance->mHandles.GetHandle(&hash,
getter_AddRefs(handle)); if (handle) { // We doom any active handle in CacheFileIOManager::EvictByContext(), so // this must be a new one. Skip it.
LOG(
("CacheFileContextEvictor::EvictEntries() - Skipping entry since we " "found an active handle. [handle=%p]",
handle.get())); continue;
}
CacheIndex::EntryStatus status; bool pinned = false; auto callback = [&pinned](const CacheIndexEntry* aEntry) {
pinned = aEntry->IsPinned();
};
rv = CacheIndex::HasEntry(hash, &status, callback); // This must never fail, since eviction (this code) happens only when the // index is up-to-date and thus the informatin is known.
MOZ_ASSERT(NS_SUCCEEDED(rv));
if (pinned != mEntries[0]->mPinned) {
LOG(
("CacheFileContextEvictor::EvictEntries() - Skipping entry since " "pinning " "doesn't match [evicting pinned=%d, entry pinned=%d]",
mEntries[0]->mPinned, pinned)); continue;
}
if (!mEntries[0]->mOrigin.IsEmpty()) {
nsCOMPtr<nsIFile> file;
CacheFileIOManager::gInstance->GetFile(&hash, getter_AddRefs(file));
// Read metadata from the file synchronously
RefPtr<CacheFileMetadata> metadata = new CacheFileMetadata();
rv = metadata->SyncReadMetadata(file); if (NS_WARN_IF(NS_FAILED(rv))) { continue;
}
// Now get the context + enhance id + URL from the key.
nsAutoCString uriSpec;
RefPtr<nsILoadContextInfo> info =
CacheFileUtils::ParseKey(metadata->GetKey(), nullptr, &uriSpec);
MOZ_ASSERT(info); if (!info) { continue;
}
nsCOMPtr<nsIURI> uri;
rv = NS_NewURI(getter_AddRefs(uri), uriSpec); if (NS_FAILED(rv)) {
LOG(
("CacheFileContextEvictor::EvictEntries() - Skipping entry since " "NS_NewURI failed to parse the uriSpec")); continue;
}
nsAutoString urlOrigin;
rv = nsContentUtils::GetWebExposedOriginSerialization(uri, urlOrigin); if (NS_FAILED(rv)) {
LOG(
("CacheFileContextEvictor::EvictEntries() - Skipping entry since " "We failed to extract an origin")); continue;
}
if (!urlOrigin.Equals(mEntries[0]->mOrigin)) {
LOG(
("CacheFileContextEvictor::EvictEntries() - Skipping entry since " "origin " "doesn't match")); continue;
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung ist noch experimentell.