Bug 1894380 - Queue the AsyncApplyUpdate request if there is one executing. r=dimi

Differential Revision: https://phabricator.services.mozilla.com/D220249
This commit is contained in:
Tim Huang 2024-09-12 16:21:19 +00:00
Родитель 16c3693cdb
Коммит e3207f3af3
2 изменённых файлов: 48 добавлений и 0 удалений

Просмотреть файл

@ -124,6 +124,7 @@ nsresult Classifier::GetPrivateStoreDirectory(
Classifier::Classifier() Classifier::Classifier()
: mIsTableRequestResultOutdated(true), : mIsTableRequestResultOutdated(true),
mAsyncUpdateInProgress(false),
mUpdateInterrupted(true), mUpdateInterrupted(true),
mIsClosed(false) { mIsClosed(false) {
// Make a lazy thread for any IO // Make a lazy thread for any IO
@ -697,6 +698,8 @@ void Classifier::FlushAndDisableAsyncUpdate() {
mUpdateThread->Shutdown(); mUpdateThread->Shutdown();
mUpdateThread = nullptr; mUpdateThread = nullptr;
mPendingUpdates.Clear();
mAsyncUpdateInProgress = false;
} }
nsresult Classifier::AsyncApplyUpdates(const TableUpdateArray& aUpdates, nsresult Classifier::AsyncApplyUpdates(const TableUpdateArray& aUpdates,
@ -708,6 +711,22 @@ nsresult Classifier::AsyncApplyUpdates(const TableUpdateArray& aUpdates,
return NS_ERROR_FAILURE; return NS_ERROR_FAILURE;
} }
if (mAsyncUpdateInProgress) {
mPendingUpdates.AppendElement(NS_NewRunnableFunction(
"safebrowsing::Classifier::AsyncApplyUpdates",
[self = RefPtr{this}, aUpdates = aUpdates.Clone(),
aCallback]() mutable {
nsresult rv = self->AsyncApplyUpdates(aUpdates, aCallback);
// Calling the callback if we got an failure here to notify update
// observers.
if (NS_FAILED(rv)) {
aCallback(rv);
}
}));
return NS_OK;
}
// Caller thread | Update thread // Caller thread | Update thread
// -------------------------------------------------------- // --------------------------------------------------------
// | ApplyUpdatesBackground // | ApplyUpdatesBackground
@ -718,6 +737,7 @@ nsresult Classifier::AsyncApplyUpdates(const TableUpdateArray& aUpdates,
MOZ_ASSERT(mNewLookupCaches.IsEmpty(), MOZ_ASSERT(mNewLookupCaches.IsEmpty(),
"There should be no leftovers from a previous update."); "There should be no leftovers from a previous update.");
mAsyncUpdateInProgress = true;
mUpdateInterrupted = false; mUpdateInterrupted = false;
nsresult rv = nsresult rv =
mRootStoreDirectory->Clone(getter_AddRefs(mRootStoreDirectoryForUpdate)); mRootStoreDirectory->Clone(getter_AddRefs(mRootStoreDirectoryForUpdate));
@ -773,6 +793,8 @@ nsresult Classifier::AsyncApplyUpdates(const TableUpdateArray& aUpdates,
LOG(("Step 3. Updates applied! Fire callback.")); LOG(("Step 3. Updates applied! Fire callback."));
aCallback(rv); aCallback(rv);
classifier->AsyncUpdateFinished();
}); });
callerThread->Dispatch(fgRunnable, NS_DISPATCH_NORMAL); callerThread->Dispatch(fgRunnable, NS_DISPATCH_NORMAL);
@ -781,6 +803,22 @@ nsresult Classifier::AsyncApplyUpdates(const TableUpdateArray& aUpdates,
return mUpdateThread->Dispatch(bgRunnable, NS_DISPATCH_NORMAL); return mUpdateThread->Dispatch(bgRunnable, NS_DISPATCH_NORMAL);
} }
void Classifier::AsyncUpdateFinished() {
MOZ_ASSERT(!OnUpdateThread(),
"AsyncUpdateFinished() MUST NOT be called on update thread");
MOZ_ASSERT(!NS_IsMainThread(),
"AsyncUpdateFinished() must be called on the worker thread");
mAsyncUpdateInProgress = false;
// If there are pending updates, run the first one.
if (!mPendingUpdates.IsEmpty()) {
auto& runnable = mPendingUpdates.ElementAt(0);
runnable->Run();
mPendingUpdates.RemoveElementAt(0);
}
}
nsresult Classifier::ApplyUpdatesBackground( nsresult Classifier::ApplyUpdatesBackground(
TableUpdateArray& aUpdates, nsTArray<nsCString>& aFailedTableNames) { TableUpdateArray& aUpdates, nsTArray<nsCString>& aFailedTableNames) {
// |mUpdateInterrupted| is guaranteed to have been unset. // |mUpdateInterrupted| is guaranteed to have been unset.

Просмотреть файл

@ -205,6 +205,10 @@ class Classifier {
nsresult ApplyUpdatesForeground(nsresult aBackgroundRv, nsresult ApplyUpdatesForeground(nsresult aBackgroundRv,
const nsTArray<nsCString>& aFailedTableNames); const nsTArray<nsCString>& aFailedTableNames);
// Notify the worker thread that the async update is finished to kick off the
// pending updates.
void AsyncUpdateFinished();
// Used by worker thread and update thread to abort current operation. // Used by worker thread and update thread to abort current operation.
bool ShouldAbort() const; bool ShouldAbort() const;
@ -237,6 +241,12 @@ class Classifier {
// The copy of mLookupCaches for update only. // The copy of mLookupCaches for update only.
LookupCacheArray mNewLookupCaches; LookupCacheArray mNewLookupCaches;
// Whether an async update is in progress.
bool mAsyncUpdateInProgress;
// Pending updates to be executed after the current async update is finished.
nsTArray<nsCOMPtr<nsIRunnable>> mPendingUpdates;
// True when Reset() is called. // True when Reset() is called.
bool mUpdateInterrupted; bool mUpdateInterrupted;