mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 05:41:12 +00:00
Bug 1050613 - Make sure force-valid for HTTP cache entries is removed when entries are removed, r=michal
This commit is contained in:
parent
1314828cb9
commit
68a7636bf1
@ -545,7 +545,6 @@ already_AddRefed<CacheEntryHandle> CacheEntry::ReopenTruncated(bool aMemoryOnly,
|
||||
mUseDisk && !aMemoryOnly,
|
||||
mSkipSizeCheck,
|
||||
mPinned,
|
||||
true, // always create
|
||||
true, // truncate existing (this one)
|
||||
getter_AddRefs(handle));
|
||||
|
||||
@ -1072,13 +1071,12 @@ NS_IMETHODIMP CacheEntry::GetIsForcedValid(bool *aIsForcedValid)
|
||||
}
|
||||
|
||||
nsAutoCString key;
|
||||
|
||||
nsresult rv = HashingKeyWithStorage(key);
|
||||
nsresult rv = HashingKey(key);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
*aIsForcedValid = CacheStorageService::Self()->IsForcedValidEntry(key);
|
||||
*aIsForcedValid = CacheStorageService::Self()->IsForcedValidEntry(mStorageID, key);
|
||||
LOG(("CacheEntry::GetIsForcedValid [this=%p, IsForcedValid=%d]", this, *aIsForcedValid));
|
||||
|
||||
return NS_OK;
|
||||
@ -1089,12 +1087,12 @@ NS_IMETHODIMP CacheEntry::ForceValidFor(uint32_t aSecondsToTheFuture)
|
||||
LOG(("CacheEntry::ForceValidFor [this=%p, aSecondsToTheFuture=%d]", this, aSecondsToTheFuture));
|
||||
|
||||
nsAutoCString key;
|
||||
nsresult rv = HashingKeyWithStorage(key);
|
||||
nsresult rv = HashingKey(key);
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
CacheStorageService::Self()->ForceEntryValidFor(key, aSecondsToTheFuture);
|
||||
CacheStorageService::Self()->ForceEntryValidFor(mStorageID, key, aSecondsToTheFuture);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -1325,6 +1323,8 @@ NS_IMETHODIMP CacheEntry::AsyncDoom(nsICacheEntryDoomCallback *aCallback)
|
||||
if (mIsDoomed || mDoomCallback)
|
||||
return NS_ERROR_IN_PROGRESS; // to aggregate have DOOMING state
|
||||
|
||||
RemoveForcedValidity();
|
||||
|
||||
mIsDoomed = true;
|
||||
mDoomCallback = aCallback;
|
||||
}
|
||||
@ -1623,6 +1623,8 @@ void CacheEntry::DoomAlreadyRemoved()
|
||||
|
||||
mozilla::MutexAutoLock lock(mLock);
|
||||
|
||||
RemoveForcedValidity();
|
||||
|
||||
mIsDoomed = true;
|
||||
|
||||
// Pretend pinning is know. This entry is now doomed for good, so don't
|
||||
@ -1666,6 +1668,25 @@ void CacheEntry::DoomFile()
|
||||
OnFileDoomed(rv);
|
||||
}
|
||||
|
||||
void CacheEntry::RemoveForcedValidity()
|
||||
{
|
||||
mLock.AssertCurrentThreadOwns();
|
||||
|
||||
nsresult rv;
|
||||
|
||||
if (mIsDoomed) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsAutoCString entryKey;
|
||||
rv = HashingKey(entryKey);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return;
|
||||
}
|
||||
|
||||
CacheStorageService::Self()->RemoveEntryForceValid(mStorageID, entryKey);
|
||||
}
|
||||
|
||||
void CacheEntry::BackgroundOp(uint32_t aOperations, bool aForceAsync)
|
||||
{
|
||||
mLock.AssertCurrentThreadOwns();
|
||||
|
@ -266,6 +266,9 @@ private:
|
||||
|
||||
// Called only from DoomAlreadyRemoved()
|
||||
void DoomFile();
|
||||
// When this entry is doomed the first time, this method removes
|
||||
// any force-valid timing info for this entry.
|
||||
void RemoveForcedValidity();
|
||||
|
||||
already_AddRefed<CacheEntryHandle> ReopenTruncated(bool aMemoryOnly,
|
||||
nsICacheEntryOpenCallback* aCallback);
|
||||
|
@ -104,7 +104,6 @@ NS_IMETHODIMP CacheStorage::AsyncOpenURI(nsIURI *aURI,
|
||||
RefPtr<CacheEntryHandle> entry;
|
||||
rv = CacheStorageService::Self()->AddStorageEntry(
|
||||
this, noRefURI, aIdExtension,
|
||||
true, // create always
|
||||
truncate, // replace any existing one?
|
||||
getter_AddRefs(entry));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
@ -131,7 +130,6 @@ NS_IMETHODIMP CacheStorage::OpenTruncate(nsIURI *aURI, const nsACString & aIdExt
|
||||
RefPtr<CacheEntryHandle> handle;
|
||||
rv = CacheStorageService::Self()->AddStorageEntry(
|
||||
this, noRefURI, aIdExtension,
|
||||
true, // create always
|
||||
true, // replace any existing one
|
||||
getter_AddRefs(handle));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
@ -769,6 +769,11 @@ NS_IMETHODIMP CacheStorageService::Clear()
|
||||
{
|
||||
mozilla::MutexAutoLock lock(mLock);
|
||||
|
||||
{
|
||||
mozilla::MutexAutoLock forcedValidEntriesLock(mForcedValidEntriesLock);
|
||||
mForcedValidEntries.Clear();
|
||||
}
|
||||
|
||||
NS_ENSURE_TRUE(!mShutdown, NS_ERROR_NOT_INITIALIZED);
|
||||
|
||||
nsTArray<nsCString> keys;
|
||||
@ -1021,7 +1026,7 @@ CacheStorageService::RemoveEntry(CacheEntry* aEntry, bool aOnlyUnreferenced)
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!aEntry->IsUsingDisk() && IsForcedValidEntry(entryKey)) {
|
||||
if (!aEntry->IsUsingDisk() && IsForcedValidEntry(aEntry->GetStorageID(), entryKey)) {
|
||||
LOG((" forced valid, not removing"));
|
||||
return false;
|
||||
}
|
||||
@ -1094,13 +1099,19 @@ CacheStorageService::RecordMemoryOnlyEntry(CacheEntry* aEntry,
|
||||
|
||||
// Checks if a cache entry is forced valid (will be loaded directly from cache
|
||||
// without further validation) - see nsICacheEntry.idl for further details
|
||||
bool CacheStorageService::IsForcedValidEntry(nsACString &aCacheEntryKey)
|
||||
bool CacheStorageService::IsForcedValidEntry(nsACString const &aContextKey,
|
||||
nsACString const &aEntryKey)
|
||||
{
|
||||
return IsForcedValidEntry(aContextKey + aEntryKey);
|
||||
}
|
||||
|
||||
bool CacheStorageService::IsForcedValidEntry(nsACString const &aContextEntryKey)
|
||||
{
|
||||
mozilla::MutexAutoLock lock(mForcedValidEntriesLock);
|
||||
|
||||
TimeStamp validUntil;
|
||||
|
||||
if (!mForcedValidEntries.Get(aCacheEntryKey, &validUntil)) {
|
||||
if (!mForcedValidEntries.Get(aContextEntryKey, &validUntil)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -1114,13 +1125,14 @@ bool CacheStorageService::IsForcedValidEntry(nsACString &aCacheEntryKey)
|
||||
}
|
||||
|
||||
// Entry timeout has been reached
|
||||
mForcedValidEntries.Remove(aCacheEntryKey);
|
||||
mForcedValidEntries.Remove(aContextEntryKey);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Allows a cache entry to be loaded directly from cache without further
|
||||
// validation - see nsICacheEntry.idl for further details
|
||||
void CacheStorageService::ForceEntryValidFor(nsACString &aCacheEntryKey,
|
||||
void CacheStorageService::ForceEntryValidFor(nsACString const &aContextKey,
|
||||
nsACString const &aEntryKey,
|
||||
uint32_t aSecondsToTheFuture)
|
||||
{
|
||||
mozilla::MutexAutoLock lock(mForcedValidEntriesLock);
|
||||
@ -1131,7 +1143,15 @@ void CacheStorageService::ForceEntryValidFor(nsACString &aCacheEntryKey,
|
||||
// This will be the timeout
|
||||
TimeStamp validUntil = now + TimeDuration::FromSeconds(aSecondsToTheFuture);
|
||||
|
||||
mForcedValidEntries.Put(aCacheEntryKey, validUntil);
|
||||
mForcedValidEntries.Put(aContextKey + aEntryKey, validUntil);
|
||||
}
|
||||
|
||||
void CacheStorageService::RemoveEntryForceValid(nsACString const &aContextKey,
|
||||
nsACString const &aEntryKey)
|
||||
{
|
||||
mozilla::MutexAutoLock lock(mForcedValidEntriesLock);
|
||||
|
||||
mForcedValidEntries.Remove(aContextKey + aEntryKey);
|
||||
}
|
||||
|
||||
// Cleans out the old entries in mForcedValidEntries
|
||||
@ -1378,7 +1398,6 @@ nsresult
|
||||
CacheStorageService::AddStorageEntry(CacheStorage const* aStorage,
|
||||
nsIURI* aURI,
|
||||
const nsACString & aIdExtension,
|
||||
bool aCreateIfNotExist,
|
||||
bool aReplace,
|
||||
CacheEntryHandle** aResult)
|
||||
{
|
||||
@ -1393,7 +1412,7 @@ CacheStorageService::AddStorageEntry(CacheStorage const* aStorage,
|
||||
aStorage->WriteToDisk(),
|
||||
aStorage->SkipSizeCheck(),
|
||||
aStorage->Pinning(),
|
||||
aCreateIfNotExist, aReplace,
|
||||
aReplace,
|
||||
aResult);
|
||||
}
|
||||
|
||||
@ -1404,7 +1423,6 @@ CacheStorageService::AddStorageEntry(nsCSubstring const& aContextKey,
|
||||
bool aWriteToDisk,
|
||||
bool aSkipSizeCheck,
|
||||
bool aPin,
|
||||
bool aCreateIfNotExist,
|
||||
bool aReplace,
|
||||
CacheEntryHandle** aResult)
|
||||
{
|
||||
@ -1440,7 +1458,7 @@ CacheStorageService::AddStorageEntry(nsCSubstring const& aContextKey,
|
||||
if (entryExists && !aReplace) {
|
||||
// check whether we want to turn this entry to a memory-only.
|
||||
if (MOZ_UNLIKELY(!aWriteToDisk) && MOZ_LIKELY(entry->IsUsingDisk())) {
|
||||
LOG((" entry is persistnet but we want mem-only, replacing it"));
|
||||
LOG((" entry is persistent but we want mem-only, replacing it"));
|
||||
aReplace = true;
|
||||
}
|
||||
}
|
||||
@ -1457,10 +1475,20 @@ CacheStorageService::AddStorageEntry(nsCSubstring const& aContextKey,
|
||||
|
||||
entry = nullptr;
|
||||
entryExists = false;
|
||||
|
||||
// Would only lead to deleting force-valid timestamp again. We don't need the
|
||||
// replace information anymore after this point anyway.
|
||||
aReplace = false;
|
||||
}
|
||||
|
||||
// Ensure entry for the particular URL, if not read/only
|
||||
if (!entryExists && (aCreateIfNotExist || aReplace)) {
|
||||
// Ensure entry for the particular URL
|
||||
if (!entryExists) {
|
||||
// When replacing with a new entry, always remove the current force-valid timestamp,
|
||||
// this is the only place to do it.
|
||||
if (aReplace) {
|
||||
RemoveEntryForceValid(aContextKey, entryKey);
|
||||
}
|
||||
|
||||
// Entry is not in the hashtable or has just been truncated...
|
||||
entry = new CacheEntry(aContextKey, aURI, aIdExtension, aWriteToDisk, aSkipSizeCheck, aPin);
|
||||
entries->Put(entryKey, entry);
|
||||
@ -1639,6 +1667,10 @@ CacheStorageService::DoomStorageEntry(CacheStorage const* aStorage,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!entry) {
|
||||
RemoveEntryForceValid(contextKey, entryKey);
|
||||
}
|
||||
}
|
||||
|
||||
if (entry) {
|
||||
@ -1764,6 +1796,21 @@ CacheStorageService::DoomStorageEntries(nsCSubstring const& aContextKey,
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
mozilla::MutexAutoLock lock(mForcedValidEntriesLock);
|
||||
|
||||
for (auto iter = mForcedValidEntries.Iter(); !iter.Done(); iter.Next()) {
|
||||
bool matches;
|
||||
DebugOnly<nsresult> rv = CacheFileUtils::KeyMatchesLoadContextInfo(
|
||||
iter.Key(), aContext, &matches);
|
||||
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
||||
|
||||
if (matches) {
|
||||
iter.Remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// An artificial callback. This is a candidate for removal tho. In the new
|
||||
// cache any 'doom' or 'evict' function ensures that the entry or entries
|
||||
// being doomed is/are not accessible after the function returns. So there is
|
||||
@ -1824,24 +1871,28 @@ CacheStorageService::CacheFileDoomed(nsILoadContextInfo* aLoadContextInfo,
|
||||
|
||||
mozilla::MutexAutoLock lock(mLock);
|
||||
|
||||
if (mShutdown)
|
||||
if (mShutdown) {
|
||||
return;
|
||||
}
|
||||
|
||||
CacheEntryTable* entries;
|
||||
if (!sGlobalEntryTables->Get(contextKey, &entries))
|
||||
return;
|
||||
|
||||
RefPtr<CacheEntry> entry;
|
||||
if (!entries->Get(entryKey, getter_AddRefs(entry)))
|
||||
return;
|
||||
|
||||
if (!entry->IsFileDoomed())
|
||||
return;
|
||||
if (sGlobalEntryTables->Get(contextKey, &entries) &&
|
||||
entries->Get(entryKey, getter_AddRefs(entry))) {
|
||||
if (entry->IsFileDoomed()) {
|
||||
// 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();
|
||||
}
|
||||
|
||||
// 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();
|
||||
// Entry found, but it's not the entry that has been found doomed
|
||||
// by the lower eviction layer. Just leave everything unchanged.
|
||||
return;
|
||||
}
|
||||
|
||||
RemoveEntryForceValid(contextKey, entryKey);
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -158,23 +158,35 @@ private:
|
||||
* directly from cache) for the given number of seconds
|
||||
* See nsICacheEntry.idl for more details
|
||||
*/
|
||||
void ForceEntryValidFor(nsACString &aCacheEntryKey,
|
||||
void ForceEntryValidFor(nsACString const &aContextKey,
|
||||
nsACString const &aEntryKey,
|
||||
uint32_t aSecondsToTheFuture);
|
||||
|
||||
/**
|
||||
* Remove the validity info
|
||||
*/
|
||||
void RemoveEntryForceValid(nsACString const &aContextKey,
|
||||
nsACString const &aEntryKey);
|
||||
|
||||
/**
|
||||
* Retrieves the status of the cache entry to see if it has been forced valid
|
||||
* (so it will loaded directly from cache without further validation)
|
||||
*/
|
||||
bool IsForcedValidEntry(nsACString const &aContextKey,
|
||||
nsACString const &aEntryKey);
|
||||
|
||||
private:
|
||||
friend class CacheIndex;
|
||||
|
||||
/**
|
||||
* Retrieves the status of the cache entry to see if it has been forced valid
|
||||
* (so it will loaded directly from cache without further validation)
|
||||
* CacheIndex uses this to prevent a cache entry from being prememptively
|
||||
* thrown away when forced valid
|
||||
* See nsICacheEntry.idl for more details
|
||||
*/
|
||||
bool IsForcedValidEntry(nsACString &aCacheEntryKey);
|
||||
bool IsForcedValidEntry(nsACString const &aEntryKeyWithContext);
|
||||
|
||||
private:
|
||||
// These are helpers for telemetry monitorying of the memory pools.
|
||||
// These are helpers for telemetry monitoring of the memory pools.
|
||||
void TelemetryPrune(TimeStamp &now);
|
||||
void TelemetryRecordEntryCreation(CacheEntry const* entry);
|
||||
void TelemetryRecordEntryRemoval(CacheEntry const* entry);
|
||||
@ -190,7 +202,6 @@ private:
|
||||
nsresult AddStorageEntry(CacheStorage const* aStorage,
|
||||
nsIURI* aURI,
|
||||
const nsACString & aIdExtension,
|
||||
bool aCreateIfNotExist,
|
||||
bool aReplace,
|
||||
CacheEntryHandle** aResult);
|
||||
|
||||
@ -286,7 +297,6 @@ private:
|
||||
bool aWriteToDisk,
|
||||
bool aSkipSizeCheck,
|
||||
bool aPin,
|
||||
bool aCreateIfNotExist,
|
||||
bool aReplace,
|
||||
CacheEntryHandle** aResult);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user