nsresult ParentRunnable::OpenCacheFileForWrite() { AssertIsOnIOThread(); MOZ_ASSERT(mState == eReadyToReadMetadata); MOZ_ASSERT(mOpenMode == eOpenForWrite); mFileSize = mWriteParams.mSize; // Kick out the oldest entry in the LRU queue in the metadata. mModuleIndex = mMetadata.mEntries[Metadata::kLastEntry].mModuleIndex; nsCOMPtr<nsIFile> file; nsresult rv = GetCacheFile(mDirectory, mModuleIndex, getter_AddRefs(file)); NS_ENSURE_SUCCESS(rv, rv); QuotaManager* qm = QuotaManager::Get(); MOZ_ASSERT(qm, "We are on the QuotaManager's IO thread"); // Create the QuotaObject before all file IO and keep it alive until caching // completes to get maximum assertion coverage in QuotaManager against // concurrent removal, etc. mQuotaObject = qm->GetQuotaObject(quota::PERSISTENCE_TYPE_TEMPORARY, mGroup, mOrigin, file); NS_ENSURE_STATE(mQuotaObject); if (!mQuotaObject->MaybeUpdateSize(mWriteParams.mSize, /* aTruncate */ false)) { // If the request fails, it might be because mOrigin is using too much // space (MaybeUpdateSize will not evict our own origin since it is // active). Try to make some space by evicting LRU entries until there is // enough space. EvictEntries(mDirectory, mGroup, mOrigin, mWriteParams.mSize, mMetadata); if (!mQuotaObject->MaybeUpdateSize(mWriteParams.mSize, /* aTruncate */ false)) { mResult = JS::AsmJSCache_QuotaExceeded; return NS_ERROR_FAILURE; } } int32_t openFlags = PR_RDWR | PR_TRUNCATE | PR_CREATE_FILE; rv = file->OpenNSPRFileDesc(openFlags, 0644, &mFileDesc); NS_ENSURE_SUCCESS(rv, rv); // Move the mModuleIndex's LRU entry to the recent end of the queue. PodMove(mMetadata.mEntries + 1, mMetadata.mEntries, Metadata::kLastEntry); Metadata::Entry& entry = mMetadata.mEntries[0]; entry.mFastHash = mWriteParams.mFastHash; entry.mNumChars = mWriteParams.mNumChars; entry.mFullHash = mWriteParams.mFullHash; entry.mModuleIndex = mModuleIndex; rv = WriteMetadataFile(mMetadataFile, mMetadata); NS_ENSURE_SUCCESS(rv, rv); return NS_OK; }
nsresult ParentRunnable::OpenCacheFileForRead() { AssertIsOnIOThread(); MOZ_ASSERT(mState == eReadyToOpenCacheFileForRead); MOZ_ASSERT(mOpenMode == eOpenForRead); nsCOMPtr<nsIFile> file; nsresult rv = GetCacheFile(mDirectory, mModuleIndex, getter_AddRefs(file)); NS_ENSURE_SUCCESS(rv, rv); QuotaManager* qm = QuotaManager::Get(); MOZ_ASSERT(qm, "We are on the QuotaManager's IO thread"); // Even though it's not strictly necessary, create the QuotaObject before all // file IO and keep it alive until caching completes to get maximum assertion // coverage in QuotaManager against concurrent removal, etc. mQuotaObject = qm->GetQuotaObject(quota::PERSISTENCE_TYPE_TEMPORARY, mGroup, mOrigin, file); NS_ENSURE_STATE(mQuotaObject); rv = file->GetFileSize(&mFileSize); NS_ENSURE_SUCCESS(rv, rv); int32_t openFlags = PR_RDONLY | nsIFile::OS_READAHEAD; rv = file->OpenNSPRFileDesc(openFlags, 0644, &mFileDesc); NS_ENSURE_SUCCESS(rv, rv); // Move the mModuleIndex's LRU entry to the recent end of the queue. unsigned lruIndex = 0; while (mMetadata.mEntries[lruIndex].mModuleIndex != mModuleIndex) { if (++lruIndex == Metadata::kNumEntries) { return NS_ERROR_UNEXPECTED; } } Metadata::Entry entry = mMetadata.mEntries[lruIndex]; PodMove(mMetadata.mEntries + 1, mMetadata.mEntries, lruIndex); mMetadata.mEntries[0] = entry; rv = WriteMetadataFile(mMetadataFile, mMetadata); NS_ENSURE_SUCCESS(rv, rv); return NS_OK; }
nsresult FileQuotaStream<FileStreamBase>::DoOpen() { QuotaManager* quotaManager = QuotaManager::Get(); NS_ASSERTION(quotaManager, "Shouldn't be null!"); NS_ASSERTION(!mQuotaObject, "Creating quota object more than once?"); mQuotaObject = quotaManager->GetQuotaObject(mPersistenceType, mGroup, mOrigin, FileStreamBase::mOpenParams.localFile); nsresult rv = FileStreamBase::DoOpen(); NS_ENSURE_SUCCESS(rv, rv); if (mQuotaObject && (FileStreamBase::mOpenParams.ioFlags & PR_TRUNCATE)) { mQuotaObject->MaybeUpdateSize(0, /* aTruncate */ true); } return NS_OK; }