void DOMStorageDBThread::ThreadFunc() { nsresult rv = InitDatabase(); MonitorAutoLock lockMonitor(mMonitor); if (NS_FAILED(rv)) { mStatus = rv; mStopIOThread = true; return; } while (MOZ_LIKELY(!mStopIOThread || mPreloads.Length() || mPendingTasks.HasTasks())) { if (MOZ_UNLIKELY(TimeUntilFlush() == 0)) { // Flush time is up or flush has been forced, do it now. UnscheduleFlush(); if (mPendingTasks.Prepare()) { { MonitorAutoUnlock unlockMonitor(mMonitor); rv = mPendingTasks.Execute(this); } if (!mPendingTasks.Finalize(rv)) { mStatus = rv; NS_WARNING("localStorage DB access broken"); } } NotifyFlushCompletion(); } else if (MOZ_LIKELY(mPreloads.Length())) { nsAutoPtr<DBOperation> op(mPreloads[0]); mPreloads.RemoveElementAt(0); { MonitorAutoUnlock unlockMonitor(mMonitor); op->PerformAndFinalize(this); } if (op->Type() == DBOperation::opPreloadUrgent) { SetDefaultPriority(); // urgent preload unscheduled } } else if (MOZ_UNLIKELY(!mStopIOThread)) { lockMonitor.Wait(TimeUntilFlush()); } } // thread loop mStatus = ShutdownDatabase(); }
void StorageDBThread::SyncPreload(StorageCacheBridge* aCache, bool aForceSync) { PROFILER_LABEL_FUNC(js::ProfileEntry::Category::STORAGE); if (!aForceSync && aCache->LoadedCount()) { // Preload already started for this cache, just wait for it to finish. // LoadWait will exit after LoadDone on the cache has been called. SetHigherPriority(); aCache->LoadWait(); SetDefaultPriority(); return; } // Bypass sync load when an update is pending in the queue to write, we would // get incosistent data in the cache. Also don't allow sync main-thread // preload when DB open and init is still pending on the background thread. if (mDBReady && mWALModeEnabled) { bool pendingTasks; { MonitorAutoLock monitor(mThreadObserver->GetMonitor()); pendingTasks = mPendingTasks.IsOriginUpdatePending(aCache->OriginSuffix(), aCache->OriginNoSuffix()) || mPendingTasks.IsOriginClearPending(aCache->OriginSuffix(), aCache->OriginNoSuffix()); } if (!pendingTasks) { // WAL is enabled, thus do the load synchronously on the main thread. DBOperation preload(DBOperation::opPreload, aCache); preload.PerformAndFinalize(this); return; } } // Need to go asynchronously since WAL is not allowed or scheduled updates // need to be flushed first. // Schedule preload for this cache as the first operation. nsresult rv = InsertDBOp(new DBOperation(DBOperation::opPreloadUrgent, aCache)); // LoadWait exits after LoadDone of the cache has been called. if (NS_SUCCEEDED(rv)) { aCache->LoadWait(); } }
void DOMStorageDBThread::ThreadFunc() { nsresult rv = InitDatabase(); MonitorAutoLock lockMonitor(mThreadObserver->GetMonitor()); if (NS_FAILED(rv)) { mStatus = rv; mStopIOThread = true; return; } // Create an nsIThread for the current PRThread, so we can observe runnables // dispatched to it. nsCOMPtr<nsIThread> thread = NS_GetCurrentThread(); nsCOMPtr<nsIThreadInternal> threadInternal = do_QueryInterface(thread); MOZ_ASSERT(threadInternal); // Should always succeed. threadInternal->SetObserver(mThreadObserver); while (MOZ_LIKELY(!mStopIOThread || mPreloads.Length() || mPendingTasks.HasTasks() || mThreadObserver->HasPendingEvents())) { // Process xpcom events first. while (MOZ_UNLIKELY(mThreadObserver->HasPendingEvents())) { mThreadObserver->ClearPendingEvents(); MonitorAutoUnlock unlock(mThreadObserver->GetMonitor()); bool processedEvent; do { rv = thread->ProcessNextEvent(false, &processedEvent); } while (NS_SUCCEEDED(rv) && processedEvent); } if (MOZ_UNLIKELY(TimeUntilFlush() == 0)) { // Flush time is up or flush has been forced, do it now. UnscheduleFlush(); if (mPendingTasks.Prepare()) { { MonitorAutoUnlock unlockMonitor(mThreadObserver->GetMonitor()); rv = mPendingTasks.Execute(this); } if (!mPendingTasks.Finalize(rv)) { mStatus = rv; NS_WARNING("localStorage DB access broken"); } } NotifyFlushCompletion(); } else if (MOZ_LIKELY(mPreloads.Length())) { nsAutoPtr<DBOperation> op(mPreloads[0]); mPreloads.RemoveElementAt(0); { MonitorAutoUnlock unlockMonitor(mThreadObserver->GetMonitor()); op->PerformAndFinalize(this); } if (op->Type() == DBOperation::opPreloadUrgent) { SetDefaultPriority(); // urgent preload unscheduled } } else if (MOZ_UNLIKELY(!mStopIOThread)) { lockMonitor.Wait(TimeUntilFlush()); } } // thread loop mStatus = ShutdownDatabase(); if (threadInternal) { threadInternal->SetObserver(nullptr); } }