nsresult FileHandleBase::CreateParallelStream(nsISupports** aStream) { MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!"); MutableFileBase* mutableFile = MutableFile(); if (mutableFile->IsInvalid()) { return NS_ERROR_NOT_AVAILABLE; } nsCOMPtr<nsISupports> stream = mutableFile->CreateStream(mMode == FileMode::Readonly); NS_ENSURE_TRUE(stream, NS_ERROR_FAILURE); mParallelStreams.AppendElement(stream); stream.forget(aStream); return NS_OK; }
nsresult FileService::Enqueue(FileHandleBase* aFileHandle, FileHelper* aFileHelper) { MOZ_ASSERT(NS_IsMainThread(), "Wrong thread!"); MOZ_ASSERT(aFileHandle, "Null pointer!"); MutableFileBase* mutableFile = aFileHandle->MutableFile(); if (mutableFile->IsInvalid()) { return NS_ERROR_NOT_AVAILABLE; } const nsACString& storageId = mutableFile->mStorageId; const nsAString& fileName = mutableFile->mFileName; bool modeIsWrite = aFileHandle->mMode == FileMode::Readwrite; StorageInfo* storageInfo; if (!mStorageInfos.Get(storageId, &storageInfo)) { nsAutoPtr<StorageInfo> newStorageInfo(new StorageInfo()); mStorageInfos.Put(storageId, newStorageInfo); storageInfo = newStorageInfo.forget(); } FileHandleQueue* existingFileHandleQueue = storageInfo->GetFileHandleQueue(aFileHandle); if (existingFileHandleQueue) { existingFileHandleQueue->Enqueue(aFileHelper); return NS_OK; } bool lockedForReading = storageInfo->IsFileLockedForReading(fileName); bool lockedForWriting = storageInfo->IsFileLockedForWriting(fileName); if (modeIsWrite) { if (!lockedForWriting) { storageInfo->LockFileForWriting(fileName); } } else { if (!lockedForReading) { storageInfo->LockFileForReading(fileName); } } if (lockedForWriting || (lockedForReading && modeIsWrite)) { storageInfo->CreateDelayedEnqueueInfo(aFileHandle, aFileHelper); } else { FileHandleQueue* fileHandleQueue = storageInfo->CreateFileHandleQueue(aFileHandle); if (aFileHelper) { // Enqueue() will queue the file helper if there's already something // running. That can't fail, so no need to eventually remove // storageInfo from the hash table. // // If the file helper is free to run then AsyncRun() is called on the // file helper. AsyncRun() is responsible for calling all necessary // callbacks when something fails. We're propagating the error here, // however there's no need to eventually remove storageInfo from // the hash table. Code behind AsyncRun() will take care of it. The last // item in the code path is NotifyFileHandleCompleted() which removes // storageInfo from the hash table if there are no file handles for // the file storage. nsresult rv = fileHandleQueue->Enqueue(aFileHelper); NS_ENSURE_SUCCESS(rv, rv); } } return NS_OK; }