void FileService::NotifyLockedFileCompleted(LockedFile* aLockedFile) { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); NS_ASSERTION(aLockedFile, "Null pointer!"); FileHandle* fileHandle = aLockedFile->mFileHandle; const nsACString& storageId = fileHandle->mFileStorage->Id(); FileStorageInfo* fileStorageInfo; if (!mFileStorageInfos.Get(storageId, &fileStorageInfo)) { NS_ERROR("We don't know anyting about this locked file?!"); return; } fileStorageInfo->RemoveLockedFileQueue(aLockedFile); if (!fileStorageInfo->HasRunningLockedFiles()) { mFileStorageInfos.Remove(storageId); // See if we need to fire any complete callbacks. uint32_t index = 0; while (index < mCompleteCallbacks.Length()) { if (MaybeFireCallback(mCompleteCallbacks[index])) { mCompleteCallbacks.RemoveElementAt(index); } else { index++; } } } }
bool FileService::HasLockedFilesForStorage(nsIFileStorage* aFileStorage) { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); NS_ASSERTION(aFileStorage, "Null pointer!"); FileStorageInfo* fileStorageInfo; if (!mFileStorageInfos.Get(aFileStorage->StorageId(), &fileStorageInfo)) { return false; } return fileStorageInfo->HasRunningLockedFiles(aFileStorage); }
void FileService::AbortLockedFilesForStorage(nsIFileStorage* aFileStorage) { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); NS_ASSERTION(aFileStorage, "Null pointer!"); FileStorageInfo* fileStorageInfo; if (!mFileStorageInfos.Get(aFileStorage->StorageId(), &fileStorageInfo)) { return; } nsAutoTArray<nsRefPtr<LockedFile>, 10> lockedFiles; fileStorageInfo->CollectRunningAndDelayedLockedFiles(aFileStorage, lockedFiles); for (PRUint32 index = 0; index < lockedFiles.Length(); index++) { lockedFiles[index]->Abort(); } }
nsresult FileService::Enqueue(LockedFile* aLockedFile, FileHelper* aFileHelper) { NS_ASSERTION(NS_IsMainThread(), "Wrong thread!"); NS_ASSERTION(aLockedFile, "Null pointer!"); FileHandle* fileHandle = aLockedFile->mFileHandle; if (fileHandle->mFileStorage->IsStorageInvalidated()) { return NS_ERROR_NOT_AVAILABLE; } nsISupports* storageId = fileHandle->mFileStorage->StorageId(); const nsAString& fileName = fileHandle->mFileName; bool modeIsWrite = aLockedFile->mMode == LockedFile::READ_WRITE; FileStorageInfo* fileStorageInfo; if (!mFileStorageInfos.Get(storageId, &fileStorageInfo)) { nsAutoPtr<FileStorageInfo> newFileStorageInfo(new FileStorageInfo()); mFileStorageInfos.Put(storageId, newFileStorageInfo); fileStorageInfo = newFileStorageInfo.forget(); } LockedFileQueue* existingLockedFileQueue = fileStorageInfo->GetLockedFileQueue(aLockedFile); if (existingLockedFileQueue) { existingLockedFileQueue->Enqueue(aFileHelper); return NS_OK; } bool lockedForReading = fileStorageInfo->IsFileLockedForReading(fileName); bool lockedForWriting = fileStorageInfo->IsFileLockedForWriting(fileName); if (modeIsWrite) { if (!lockedForWriting) { fileStorageInfo->LockFileForWriting(fileName); } } else { if (!lockedForReading) { fileStorageInfo->LockFileForReading(fileName); } } if (lockedForWriting || (lockedForReading && modeIsWrite)) { fileStorageInfo->CreateDelayedEnqueueInfo(aLockedFile, aFileHelper); } else { LockedFileQueue* lockedFileQueue = fileStorageInfo->CreateLockedFileQueue(aLockedFile); if (aFileHelper) { // Enqueue() will queue the file helper if there's already something // running. That can't fail, so no need to eventually remove // fileStorageInfo 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 fileStorageInfo from // the hash table. Code behind AsyncRun() will take care of it. The last // item in the code path is NotifyLockedFileCompleted() which removes // fileStorageInfo from the hash table if there are no locked files for // the file storage. nsresult rv = lockedFileQueue->Enqueue(aFileHelper); NS_ENSURE_SUCCESS(rv, rv); } } return NS_OK; }