NS_IMETHODIMP _OldCacheEntryWrapper::AsyncDoom(nsICacheEntryDoomCallback* listener) { RefPtr<DoomCallbackWrapper> cb = listener ? new DoomCallbackWrapper(listener) : nullptr; return AsyncDoom(cb); }
NS_IMETHODIMP CacheEntry::SetPredictedDataSize(int64_t aPredictedDataSize) { mPredictedDataSize = aPredictedDataSize; if (CacheObserver::EntryIsTooBig(mPredictedDataSize, mUseDisk)) { LOG(("CacheEntry::SetPredictedDataSize [this=%p] too big, dooming", this)); AsyncDoom(nullptr); return NS_ERROR_FILE_TOO_BIG; } return NS_OK; }
already_AddRefed<CacheEntryHandle> CacheEntry::ReopenTruncated(bool aMemoryOnly, nsICacheEntryOpenCallback* aCallback) { LOG(("CacheEntry::ReopenTruncated [this=%p]", this)); mLock.AssertCurrentThreadOwns(); // Hold callbacks invocation, AddStorageEntry would invoke from doom prematurly mPreventCallbacks = true; nsRefPtr<CacheEntryHandle> handle; nsRefPtr<CacheEntry> newEntry; { mozilla::MutexAutoUnlock unlock(mLock); // The following call dooms this entry (calls DoomAlreadyRemoved on us) nsresult rv = CacheStorageService::Self()->AddStorageEntry( GetStorageID(), GetURI(), GetEnhanceID(), mUseDisk && !aMemoryOnly, true, // always create true, // truncate existing (this one) getter_AddRefs(handle)); if (NS_SUCCEEDED(rv)) { newEntry = handle->Entry(); LOG((" exchanged entry %p by entry %p, rv=0x%08x", this, newEntry.get(), rv)); newEntry->AsyncOpen(aCallback, nsICacheStorage::OPEN_TRUNCATE); } else { LOG((" exchanged of entry %p failed, rv=0x%08x", this, rv)); AsyncDoom(nullptr); } } mPreventCallbacks = false; if (!newEntry) return nullptr; newEntry->TransferCallbacks(*this); mCallbacks.Clear(); // Must return a new write handle, since the consumer is expected to // write to this newly recreated entry. The |handle| is only a common // reference counter and doesn't revert entry state back when write // fails and also doesn't update the entry frecency. Not updating // frecency causes entries to not be purged from our memory pools. nsRefPtr<CacheEntryHandle> writeHandle = newEntry->NewWriteHandle(); return writeHandle.forget(); }
already_AddRefed<CacheEntryHandle> CacheEntry::ReopenTruncated(bool aMemoryOnly, nsICacheEntryOpenCallback* aCallback) { LOG(("CacheEntry::ReopenTruncated [this=%p]", this)); mLock.AssertCurrentThreadOwns(); // Hold callbacks invocation, AddStorageEntry would invoke from doom prematurly mPreventCallbacks = true; nsRefPtr<CacheEntryHandle> handle; nsRefPtr<CacheEntry> newEntry; { mozilla::MutexAutoUnlock unlock(mLock); // The following call dooms this entry (calls DoomAlreadyRemoved on us) nsresult rv = CacheStorageService::Self()->AddStorageEntry( GetStorageID(), GetURI(), GetEnhanceID(), mUseDisk && !aMemoryOnly, true, // always create true, // truncate existing (this one) getter_AddRefs(handle)); LOG((" exchanged entry %p by entry %p, rv=0x%08x", this, newEntry.get(), rv)); if (NS_SUCCEEDED(rv)) { newEntry = handle->Entry(); newEntry->AsyncOpen(aCallback, nsICacheStorage::OPEN_TRUNCATE); } else { AsyncDoom(nullptr); } } mPreventCallbacks = false; if (!newEntry) return nullptr; newEntry->TransferCallbacks(*this); mCallbacks.Clear(); return handle.forget(); }
bool CacheEntry::Load(bool aTruncate, bool aPriority) { LOG(("CacheEntry::Load [this=%p, trunc=%d]", this, aTruncate)); mLock.AssertCurrentThreadOwns(); if (mState > LOADING) { LOG((" already loaded")); return false; } if (mState == LOADING) { LOG((" already loading")); return true; } mState = LOADING; MOZ_ASSERT(!mFile); nsresult rv; nsAutoCString fileKey; rv = HashingKeyWithStorage(fileKey); // Check the index under two conditions for two states and take appropriate action: // 1. When this is a disk entry and not told to truncate, check there is a disk file. // If not, set the 'truncate' flag to true so that this entry will open instantly // as a new one. // 2. When this is a memory-only entry, check there is a disk file. // If there is or could be, doom that file. if ((!aTruncate || !mUseDisk) && NS_SUCCEEDED(rv)) { // Check the index right now to know we have or have not the entry // as soon as possible. CacheIndex::EntryStatus status; if (NS_SUCCEEDED(CacheIndex::HasEntry(fileKey, &status))) { switch (status) { case CacheIndex::DOES_NOT_EXIST: LOG((" entry doesn't exist according information from the index, truncating")); aTruncate = true; break; case CacheIndex::EXISTS: case CacheIndex::DO_NOT_KNOW: if (!mUseDisk) { LOG((" entry open as memory-only, but there is (status=%d) a file, dooming it", status)); CacheFileIOManager::DoomFileByKey(fileKey, nullptr); } break; } } } mFile = new CacheFile(); BackgroundOp(Ops::REGISTER); bool directLoad = aTruncate || !mUseDisk; if (directLoad) { // mLoadStart will be used to calculate telemetry of life-time of this entry. // Low resulution is then enough. mLoadStart = TimeStamp::NowLoRes(); } else { mLoadStart = TimeStamp::Now(); } { mozilla::MutexAutoUnlock unlock(mLock); LOG((" performing load, file=%p", mFile.get())); if (NS_SUCCEEDED(rv)) { rv = mFile->Init(fileKey, aTruncate, !mUseDisk, aPriority, directLoad ? nullptr : this); } if (NS_FAILED(rv)) { mFileStatus = rv; AsyncDoom(nullptr); return false; } } if (directLoad) { // Just fake the load has already been done as "new". mFileStatus = NS_OK; mState = EMPTY; } return mState == LOADING; }