void CacheStorageService::CacheFileDoomed(nsILoadContextInfo* aLoadContextInfo, const nsACString & aIdExtension, const nsACString & aURISpec) { nsAutoCString contextKey; CacheFileUtils::AppendKeyPrefix(aLoadContextInfo, contextKey); nsAutoCString entryKey; CacheEntry::HashingKey(EmptyCString(), aIdExtension, aURISpec, entryKey); mozilla::MutexAutoLock lock(mLock); if (mShutdown) return; CacheEntryTable* entries; if (!sGlobalEntryTables->Get(contextKey, &entries)) return; nsRefPtr<CacheEntry> entry; if (!entries->Get(entryKey, getter_AddRefs(entry))) return; if (!entry->IsFileDoomed()) return; if (entry->IsReferenced()) return; // Need to remove under the lock to avoid possible race leading // to duplication of the entry per its key. RemoveExactEntry(entries, entryKey, entry, false); entry->DoomAlreadyRemoved(); }
bool CacheStorageService::GetCacheEntryInfo(nsILoadContextInfo* aLoadContextInfo, const nsACString & aIdExtension, const nsACString & aURISpec, EntryInfoCallback *aCallback) { nsAutoCString contextKey; CacheFileUtils::AppendKeyPrefix(aLoadContextInfo, contextKey); nsAutoCString entryKey; CacheEntry::HashingKey(EmptyCString(), aIdExtension, aURISpec, entryKey); nsRefPtr<CacheEntry> entry; { mozilla::MutexAutoLock lock(mLock); if (mShutdown) { return false; } CacheEntryTable* entries; if (!sGlobalEntryTables->Get(contextKey, &entries)) { return false; } if (!entries->Get(entryKey, getter_AddRefs(entry))) { return false; } } GetCacheEntryInfo(entry, aCallback); return true; }
nsresult CacheStorageService::DoomStorageEntry(CacheStorage const* aStorage, nsIURI *aURI, const nsACString & aIdExtension, nsICacheEntryDoomCallback* aCallback) { LOG(("CacheStorageService::DoomStorageEntry")); NS_ENSURE_ARG(aStorage); NS_ENSURE_ARG(aURI); nsAutoCString contextKey; CacheFileUtils::AppendKeyPrefix(aStorage->LoadInfo(), contextKey); nsAutoCString entryKey; nsresult rv = CacheEntry::HashingKey(EmptyCString(), aIdExtension, aURI, entryKey); NS_ENSURE_SUCCESS(rv, rv); nsRefPtr<CacheEntry> entry; { mozilla::MutexAutoLock lock(mLock); NS_ENSURE_FALSE(mShutdown, NS_ERROR_NOT_INITIALIZED); CacheEntryTable* entries; if (sGlobalEntryTables->Get(contextKey, &entries)) { if (entries->Get(entryKey, getter_AddRefs(entry))) { if (aStorage->WriteToDisk() || !entry->IsUsingDiskLocked()) { // When evicting from disk storage, purge // When evicting from memory storage and the entry is memory-only, purge LOG((" purging entry %p for %s [storage use disk=%d, entry use disk=%d]", entry.get(), entryKey.get(), aStorage->WriteToDisk(), entry->IsUsingDiskLocked())); entries->Remove(entryKey); } else { // Otherwise, leave it LOG((" leaving entry %p for %s [storage use disk=%d, entry use disk=%d]", entry.get(), entryKey.get(), aStorage->WriteToDisk(), entry->IsUsingDiskLocked())); entry = nullptr; } } } } if (entry) { LOG((" dooming entry %p for %s", entry.get(), entryKey.get())); return entry->AsyncDoom(aCallback); } LOG((" no entry loaded for %s", entryKey.get())); if (aStorage->WriteToDisk()) { nsAutoCString contextKey; CacheFileUtils::AppendKeyPrefix(aStorage->LoadInfo(), contextKey); rv = CacheEntry::HashingKey(contextKey, aIdExtension, aURI, entryKey); NS_ENSURE_SUCCESS(rv, rv); LOG((" dooming file only for %s", entryKey.get())); nsRefPtr<CacheEntryDoomByKeyCallback> callback( new CacheEntryDoomByKeyCallback(aCallback)); rv = CacheFileIOManager::DoomFileByKey(entryKey, callback); NS_ENSURE_SUCCESS(rv, rv); return NS_OK; } if (aCallback) aCallback->OnCacheEntryDoomed(NS_ERROR_NOT_AVAILABLE); return NS_OK; }
nsresult CacheStorageService::AddStorageEntry(nsCSubstring const& aContextKey, nsIURI* aURI, const nsACString & aIdExtension, bool aWriteToDisk, bool aCreateIfNotExist, bool aReplace, CacheEntryHandle** aResult) { NS_ENSURE_ARG(aURI); nsresult rv; nsAutoCString entryKey; rv = CacheEntry::HashingKey(EmptyCString(), aIdExtension, aURI, entryKey); NS_ENSURE_SUCCESS(rv, rv); LOG(("CacheStorageService::AddStorageEntry [entryKey=%s, contextKey=%s]", entryKey.get(), aContextKey.BeginReading())); nsRefPtr<CacheEntry> entry; nsRefPtr<CacheEntryHandle> handle; { mozilla::MutexAutoLock lock(mLock); NS_ENSURE_FALSE(mShutdown, NS_ERROR_NOT_INITIALIZED); // Ensure storage table CacheEntryTable* entries; if (!sGlobalEntryTables->Get(aContextKey, &entries)) { entries = new CacheEntryTable(CacheEntryTable::ALL_ENTRIES); sGlobalEntryTables->Put(aContextKey, entries); LOG((" new storage entries table for context %s", aContextKey.BeginReading())); } bool entryExists = entries->Get(entryKey, getter_AddRefs(entry)); // check whether the file is already doomed if (entryExists && entry->IsFileDoomed() && !aReplace) { aReplace = true; } // If truncate is demanded, delete and doom the current entry if (entryExists && aReplace) { entries->Remove(entryKey); LOG((" dooming entry %p for %s because of OPEN_TRUNCATE", entry.get(), entryKey.get())); // On purpose called under the lock to prevent races of doom and open on I/O thread // No need to remove from both memory-only and all-entries tables. The new entry // will overwrite the shadow entry in its ctor. entry->DoomAlreadyRemoved(); entry = nullptr; entryExists = false; } if (entryExists && entry->SetUsingDisk(aWriteToDisk)) { RecordMemoryOnlyEntry(entry, !aWriteToDisk, true /* overwrite */); } // Ensure entry for the particular URL, if not read/only if (!entryExists && (aCreateIfNotExist || aReplace)) { // Entry is not in the hashtable or has just been truncated... entry = new CacheEntry(aContextKey, aURI, aIdExtension, aWriteToDisk); entries->Put(entryKey, entry); LOG((" new entry %p for %s", entry.get(), entryKey.get())); } if (entry) { // Here, if this entry was not for a long time referenced by any consumer, // gets again first 'handles count' reference. handle = entry->NewHandle(); } } handle.forget(aResult); return NS_OK; }
nsresult CacheStorageService::AddStorageEntry(nsCSubstring const& aContextKey, nsIURI* aURI, const nsACString & aIdExtension, bool aWriteToDisk, bool aCreateIfNotExist, bool aReplace, CacheEntry** aResult) { NS_ENSURE_ARG(aURI); nsresult rv; nsAutoCString entryKey; rv = CacheEntry::HashingKey(EmptyCString(), aIdExtension, aURI, entryKey); NS_ENSURE_SUCCESS(rv, rv); LOG(("CacheStorageService::AddStorageEntry [entryKey=%s, contextKey=%s]", entryKey.get(), aContextKey.BeginReading())); nsRefPtr<CacheEntry> entry; { mozilla::MutexAutoLock lock(mLock); NS_ENSURE_FALSE(mShutdown, NS_ERROR_NOT_INITIALIZED); // Ensure storage table CacheEntryTable* entries; if (!sGlobalEntryTables->Get(aContextKey, &entries)) { entries = new CacheEntryTable(); sGlobalEntryTables->Put(aContextKey, entries); LOG((" new storage entries table for context %s", aContextKey.BeginReading())); } bool entryExists = entries->Get(entryKey, getter_AddRefs(entry)); // Check entry that is memory-only is also in related memory-only hashtable. // If not, it has been evicted and we will truncate it ; doom is pending for it, // this consumer just made it sooner then the entry has actually been removed // from the master hash table. // (This can be bypassed when entry is about to be replaced anyway.) if (entryExists && !entry->UsingDisk() && !aReplace) { nsAutoCString memoryStorageID(aContextKey); AppendMemoryStorageID(memoryStorageID); CacheEntryTable* memoryEntries; aReplace = sGlobalEntryTables->Get(memoryStorageID, &memoryEntries) && memoryEntries->GetWeak(entryKey) != entry; #ifdef MOZ_LOGGING if (aReplace) { LOG((" memory-only entry %p for %s already doomed, replacing", entry.get(), entryKey.get())); } #endif } // If truncate is demanded, delete and doom the current entry if (entryExists && aReplace) { entries->Remove(entryKey); LOG((" dooming entry %p for %s because of OPEN_TRUNCATE", entry.get(), entryKey.get())); // On purpose called under the lock to prevent races of doom and open on I/O thread entry->DoomAlreadyRemoved(); entry = nullptr; entryExists = false; } if (entryExists && entry->SetUsingDisk(aWriteToDisk)) { RecordMemoryOnlyEntry(entry, !aWriteToDisk, true /* overwrite */); } // Ensure entry for the particular URL, if not read/only if (!entryExists && (aCreateIfNotExist || aReplace)) { // Entry is not in the hashtable or has just been truncated... entry = new CacheEntry(aContextKey, aURI, aIdExtension, aWriteToDisk); entries->Put(entryKey, entry); LOG((" new entry %p for %s", entry.get(), entryKey.get())); } } entry.forget(aResult); return NS_OK; }