зеркало из https://github.com/mozilla/gecko-dev.git
Backed out 2 changesets (bug 1619965) for bustages complaining about ActorsParent.cpp CLOSED TREE
Backed out changeset efa2dcf4f69e (bug 1619965) Backed out changeset da983a0216c8 (bug 1619965)
This commit is contained in:
Родитель
260d94aaaa
Коммит
9120151ddb
|
@ -6874,6 +6874,14 @@ class FactoryOp
|
|||
bool mFileHandleDisabled;
|
||||
|
||||
public:
|
||||
void NoteDatabaseBlocked(Database* aDatabase);
|
||||
|
||||
virtual void NoteDatabaseClosed(Database* aDatabase) = 0;
|
||||
|
||||
#ifdef DEBUG
|
||||
bool HasBlockedDatabases() const { return !mMaybeBlockedDatabases.IsEmpty(); }
|
||||
#endif
|
||||
|
||||
const nsCString& Origin() const {
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
|
@ -6893,14 +6901,6 @@ class FactoryOp
|
|||
return mDatabaseFilePath;
|
||||
}
|
||||
|
||||
void NoteDatabaseBlocked(Database* aDatabase);
|
||||
|
||||
void NoteDatabaseClosed(Database* aDatabase);
|
||||
|
||||
#ifdef DEBUG
|
||||
bool HasBlockedDatabases() const { return !mMaybeBlockedDatabases.IsEmpty(); }
|
||||
#endif
|
||||
|
||||
void StringifyState(nsACString& aResult) const;
|
||||
|
||||
void Stringify(nsACString& aResult) const;
|
||||
|
@ -6946,8 +6946,6 @@ class FactoryOp
|
|||
|
||||
virtual nsresult BeginVersionChange() = 0;
|
||||
|
||||
virtual bool AreActorsAlive() = 0;
|
||||
|
||||
virtual nsresult DispatchToWorkThread() = 0;
|
||||
|
||||
// Should only be called by Run().
|
||||
|
@ -7048,7 +7046,7 @@ class OpenDatabaseOp final : public FactoryOp {
|
|||
|
||||
nsresult BeginVersionChange() override;
|
||||
|
||||
bool AreActorsAlive() override;
|
||||
void NoteDatabaseClosed(Database* aDatabase) override;
|
||||
|
||||
void SendBlockedNotification() override;
|
||||
|
||||
|
@ -7119,7 +7117,7 @@ class DeleteDatabaseOp final : public FactoryOp {
|
|||
|
||||
nsresult BeginVersionChange() override;
|
||||
|
||||
bool AreActorsAlive() override;
|
||||
void NoteDatabaseClosed(Database* aDatabase) override;
|
||||
|
||||
void SendBlockedNotification() override;
|
||||
|
||||
|
@ -20510,76 +20508,6 @@ FactoryOp::FactoryOp(RefPtr<Factory> aFactory,
|
|||
MOZ_ASSERT(!QuotaClient::IsShuttingDownOnBackgroundThread());
|
||||
}
|
||||
|
||||
void FactoryOp::NoteDatabaseBlocked(Database* aDatabase) {
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(aDatabase);
|
||||
MOZ_ASSERT(mState == State::WaitingForOtherDatabasesToClose);
|
||||
MOZ_ASSERT(!mMaybeBlockedDatabases.IsEmpty());
|
||||
MOZ_ASSERT(mMaybeBlockedDatabases.Contains(aDatabase));
|
||||
|
||||
// Only send the blocked event if all databases have reported back. If the
|
||||
// database was closed then it will have been removed from the array.
|
||||
// Otherwise if it was blocked its |mBlocked| flag will be true.
|
||||
bool sendBlockedEvent = true;
|
||||
|
||||
for (auto& info : mMaybeBlockedDatabases) {
|
||||
if (info == aDatabase) {
|
||||
// This database was blocked, mark accordingly.
|
||||
info.mBlocked = true;
|
||||
} else if (!info.mBlocked) {
|
||||
// A database has not yet reported back yet, don't send the event yet.
|
||||
sendBlockedEvent = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (sendBlockedEvent) {
|
||||
SendBlockedNotification();
|
||||
}
|
||||
}
|
||||
|
||||
void FactoryOp::NoteDatabaseClosed(Database* const aDatabase) {
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(aDatabase);
|
||||
MOZ_ASSERT(mState == State::WaitingForOtherDatabasesToClose);
|
||||
MOZ_ASSERT(!mMaybeBlockedDatabases.IsEmpty());
|
||||
MOZ_ASSERT(mMaybeBlockedDatabases.Contains(aDatabase));
|
||||
|
||||
mMaybeBlockedDatabases.RemoveElement(aDatabase);
|
||||
|
||||
if (!mMaybeBlockedDatabases.IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
DatabaseActorInfo* info;
|
||||
MOZ_ALWAYS_TRUE(gLiveDatabaseHashtable->Get(mDatabaseId, &info));
|
||||
MOZ_ASSERT(info->mWaitingFactoryOp == this);
|
||||
|
||||
if (AreActorsAlive()) {
|
||||
// The IPDL strong reference has not yet been released, so we can clear
|
||||
// mWaitingFactoryOp immediately.
|
||||
info->mWaitingFactoryOp = nullptr;
|
||||
|
||||
WaitForTransactions();
|
||||
return;
|
||||
}
|
||||
|
||||
// The IPDL strong reference has been released, mWaitingFactoryOp holds the
|
||||
// last strong reference to us, so we need to move it to a stack variable
|
||||
// instead of clearing it immediately (We could clear it immediately if only
|
||||
// the other actor is destroyed, but we don't need to optimize for that, and
|
||||
// move it anyway).
|
||||
const RefPtr<FactoryOp> waitingFactoryOp = std::move(info->mWaitingFactoryOp);
|
||||
|
||||
IDB_REPORT_INTERNAL_ERR();
|
||||
SetFailureCodeIfUnset(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
|
||||
// We hold a strong ref in waitingFactoryOp, so it's safe to call Run()
|
||||
// directly.
|
||||
|
||||
mState = State::SendingResults;
|
||||
MOZ_ALWAYS_SUCCEEDS(Run());
|
||||
}
|
||||
|
||||
void FactoryOp::StringifyState(nsACString& aResult) const {
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
|
@ -21203,6 +21131,32 @@ bool FactoryOp::MustWaitFor(const FactoryOp& aExistingOp) {
|
|||
aExistingOp.mDatabaseId == mDatabaseId;
|
||||
}
|
||||
|
||||
void FactoryOp::NoteDatabaseBlocked(Database* aDatabase) {
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(mState == State::WaitingForOtherDatabasesToClose);
|
||||
MOZ_ASSERT(!mMaybeBlockedDatabases.IsEmpty());
|
||||
MOZ_ASSERT(mMaybeBlockedDatabases.Contains(aDatabase));
|
||||
|
||||
// Only send the blocked event if all databases have reported back. If the
|
||||
// database was closed then it will have been removed from the array.
|
||||
// Otherwise if it was blocked its |mBlocked| flag will be true.
|
||||
bool sendBlockedEvent = true;
|
||||
|
||||
for (auto& info : mMaybeBlockedDatabases) {
|
||||
if (info == aDatabase) {
|
||||
// This database was blocked, mark accordingly.
|
||||
info.mBlocked = true;
|
||||
} else if (!info.mBlocked) {
|
||||
// A database has not yet reported back yet, don't send the event yet.
|
||||
sendBlockedEvent = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (sendBlockedEvent) {
|
||||
SendBlockedNotification();
|
||||
}
|
||||
}
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED0(FactoryOp, DatabaseOperationBase)
|
||||
|
||||
// Run() assumes that the caller holds a strong reference to the object that
|
||||
|
@ -22090,19 +22044,66 @@ nsresult OpenDatabaseOp::BeginVersionChange() {
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
// If the actor gets destroyed, mWaitingFactoryOp will hold the last strong
|
||||
// reference to us.
|
||||
info->mWaitingFactoryOp = this;
|
||||
|
||||
mState = State::WaitingForOtherDatabasesToClose;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool OpenDatabaseOp::AreActorsAlive() {
|
||||
void OpenDatabaseOp::NoteDatabaseClosed(Database* aDatabase) {
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(mDatabase);
|
||||
MOZ_ASSERT(aDatabase);
|
||||
MOZ_ASSERT(mState == State::WaitingForOtherDatabasesToClose ||
|
||||
mState == State::WaitingForTransactionsToComplete ||
|
||||
mState == State::DatabaseWorkVersionChange);
|
||||
|
||||
return !(IsActorDestroyed() || mDatabase->IsActorDestroyed());
|
||||
if (mState != State::WaitingForOtherDatabasesToClose) {
|
||||
MOZ_ASSERT(mMaybeBlockedDatabases.IsEmpty());
|
||||
MOZ_ASSERT(
|
||||
mRequestedVersion > aDatabase->Metadata().mCommonMetadata.version(),
|
||||
"Must only be closing databases for a previous version!");
|
||||
return;
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!mMaybeBlockedDatabases.IsEmpty());
|
||||
|
||||
bool actorDestroyed = IsActorDestroyed() || mDatabase->IsActorDestroyed();
|
||||
|
||||
nsresult rv;
|
||||
if (actorDestroyed) {
|
||||
IDB_REPORT_INTERNAL_ERR();
|
||||
rv = NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
} else {
|
||||
rv = NS_OK;
|
||||
}
|
||||
|
||||
// We are being called with an assumption that mWaitingFactoryOp holds
|
||||
// a strong reference to us.
|
||||
RefPtr<OpenDatabaseOp> kungFuDeathGrip;
|
||||
|
||||
if (mMaybeBlockedDatabases.RemoveElement(aDatabase) &&
|
||||
mMaybeBlockedDatabases.IsEmpty()) {
|
||||
if (actorDestroyed) {
|
||||
DatabaseActorInfo* info;
|
||||
MOZ_ALWAYS_TRUE(gLiveDatabaseHashtable->Get(mDatabaseId, &info));
|
||||
MOZ_ASSERT(info->mWaitingFactoryOp == this);
|
||||
kungFuDeathGrip =
|
||||
static_cast<OpenDatabaseOp*>(info->mWaitingFactoryOp.get());
|
||||
info->mWaitingFactoryOp = nullptr;
|
||||
} else {
|
||||
WaitForTransactions();
|
||||
}
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
SetFailureCodeIfUnset(rv);
|
||||
|
||||
// A strong reference is held in kungFuDeathGrip, so it's safe to call Run()
|
||||
// directly.
|
||||
|
||||
mState = State::SendingResults;
|
||||
MOZ_ALWAYS_SUCCEEDS(Run());
|
||||
}
|
||||
}
|
||||
|
||||
void OpenDatabaseOp::SendBlockedNotification() {
|
||||
|
@ -22200,13 +22201,22 @@ nsresult OpenDatabaseOp::SendUpgradeNeeded() {
|
|||
void OpenDatabaseOp::SendResults() {
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(mState == State::SendingResults);
|
||||
MOZ_ASSERT(mMaybeBlockedDatabases.IsEmpty());
|
||||
MOZ_ASSERT_IF(!HasFailed(), mMaybeBlockedDatabases.IsEmpty());
|
||||
MOZ_ASSERT_IF(!HasFailed(), !mVersionChangeTransaction);
|
||||
|
||||
DebugOnly<DatabaseActorInfo*> info = nullptr;
|
||||
MOZ_ASSERT_IF(
|
||||
gLiveDatabaseHashtable && gLiveDatabaseHashtable->Get(mDatabaseId, &info),
|
||||
!info->mWaitingFactoryOp);
|
||||
mMaybeBlockedDatabases.Clear();
|
||||
|
||||
DatabaseActorInfo* info;
|
||||
if (gLiveDatabaseHashtable &&
|
||||
gLiveDatabaseHashtable->Get(mDatabaseId, &info) &&
|
||||
info->mWaitingFactoryOp) {
|
||||
MOZ_ASSERT(info->mWaitingFactoryOp == this);
|
||||
// SendResults() should only be called by Run() and Run() should only be
|
||||
// called if there's a strong reference to the object that can't be cleared
|
||||
// here, so it's safe to clear mWaitingFactoryOp without adding additional
|
||||
// strong reference.
|
||||
info->mWaitingFactoryOp = nullptr;
|
||||
}
|
||||
|
||||
if (mVersionChangeTransaction) {
|
||||
MOZ_ASSERT(HasFailed());
|
||||
|
@ -22781,8 +22791,6 @@ nsresult DeleteDatabaseOp::BeginVersionChange() {
|
|||
}
|
||||
|
||||
if (!mMaybeBlockedDatabases.IsEmpty()) {
|
||||
// If the actor gets destroyed, mWaitingFactoryOp will hold the last
|
||||
// strong reference to us.
|
||||
info->mWaitingFactoryOp = this;
|
||||
|
||||
mState = State::WaitingForOtherDatabasesToClose;
|
||||
|
@ -22796,12 +22804,6 @@ nsresult DeleteDatabaseOp::BeginVersionChange() {
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
bool DeleteDatabaseOp::AreActorsAlive() {
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
return !IsActorDestroyed();
|
||||
}
|
||||
|
||||
nsresult DeleteDatabaseOp::DispatchToWorkThread() {
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(mState == State::WaitingForTransactionsToComplete);
|
||||
|
@ -22830,6 +22832,50 @@ nsresult DeleteDatabaseOp::DispatchToWorkThread() {
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
void DeleteDatabaseOp::NoteDatabaseClosed(Database* aDatabase) {
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(mState == State::WaitingForOtherDatabasesToClose);
|
||||
MOZ_ASSERT(!mMaybeBlockedDatabases.IsEmpty());
|
||||
|
||||
bool actorDestroyed = IsActorDestroyed();
|
||||
|
||||
nsresult rv;
|
||||
if (actorDestroyed) {
|
||||
IDB_REPORT_INTERNAL_ERR();
|
||||
rv = NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
} else {
|
||||
rv = NS_OK;
|
||||
}
|
||||
|
||||
// We are being called with an assumption that mWaitingFactoryOp holds
|
||||
// a strong reference to us.
|
||||
RefPtr<OpenDatabaseOp> kungFuDeathGrip;
|
||||
|
||||
if (mMaybeBlockedDatabases.RemoveElement(aDatabase) &&
|
||||
mMaybeBlockedDatabases.IsEmpty()) {
|
||||
if (actorDestroyed) {
|
||||
DatabaseActorInfo* info;
|
||||
MOZ_ALWAYS_TRUE(gLiveDatabaseHashtable->Get(mDatabaseId, &info));
|
||||
MOZ_ASSERT(info->mWaitingFactoryOp == this);
|
||||
kungFuDeathGrip =
|
||||
static_cast<OpenDatabaseOp*>(info->mWaitingFactoryOp.get());
|
||||
info->mWaitingFactoryOp = nullptr;
|
||||
} else {
|
||||
WaitForTransactions();
|
||||
}
|
||||
}
|
||||
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
SetFailureCodeIfUnset(rv);
|
||||
|
||||
// A strong reference is held in kungFuDeathGrip, so it's safe to call Run()
|
||||
// directly.
|
||||
|
||||
mState = State::SendingResults;
|
||||
MOZ_ALWAYS_SUCCEEDS(Run());
|
||||
}
|
||||
}
|
||||
|
||||
void DeleteDatabaseOp::SendBlockedNotification() {
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(mState == State::WaitingForOtherDatabasesToClose);
|
||||
|
@ -22842,12 +22888,6 @@ void DeleteDatabaseOp::SendBlockedNotification() {
|
|||
void DeleteDatabaseOp::SendResults() {
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(mState == State::SendingResults);
|
||||
MOZ_ASSERT(mMaybeBlockedDatabases.IsEmpty());
|
||||
|
||||
DebugOnly<DatabaseActorInfo*> info = nullptr;
|
||||
MOZ_ASSERT_IF(
|
||||
gLiveDatabaseHashtable && gLiveDatabaseHashtable->Get(mDatabaseId, &info),
|
||||
!info->mWaitingFactoryOp);
|
||||
|
||||
if (!IsActorDestroyed()) {
|
||||
FactoryRequestResponse response;
|
||||
|
@ -22921,40 +22961,46 @@ void DeleteDatabaseOp::VersionChangeOp::RunOnOwningThread() {
|
|||
if (deleteOp->IsActorDestroyed()) {
|
||||
IDB_REPORT_INTERNAL_ERR();
|
||||
deleteOp->SetFailureCode(NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR);
|
||||
} else if (HasFailed()) {
|
||||
deleteOp->SetFailureCodeIfUnset(ResultCode());
|
||||
} else {
|
||||
DatabaseActorInfo* info;
|
||||
if (gLiveDatabaseHashtable->Get(deleteOp->mDatabaseId, &info) &&
|
||||
info->mWaitingFactoryOp) {
|
||||
MOZ_ASSERT(info->mWaitingFactoryOp == deleteOp);
|
||||
info->mWaitingFactoryOp = nullptr;
|
||||
}
|
||||
|
||||
// Inform all the other databases that they are now invalidated. That
|
||||
// should remove the previous metadata from our table.
|
||||
if (gLiveDatabaseHashtable->Get(deleteOp->mDatabaseId, &info)) {
|
||||
MOZ_ASSERT(!info->mLiveDatabases.IsEmpty());
|
||||
MOZ_ASSERT(!info->mWaitingFactoryOp);
|
||||
if (HasFailed()) {
|
||||
deleteOp->SetFailureCodeIfUnset(ResultCode());
|
||||
} else {
|
||||
// Inform all the other databases that they are now invalidated. That
|
||||
// should remove the previous metadata from our table.
|
||||
if (info) {
|
||||
MOZ_ASSERT(!info->mLiveDatabases.IsEmpty());
|
||||
|
||||
nsTArray<SafeRefPtr<Database>> liveDatabases;
|
||||
if (NS_WARN_IF(!liveDatabases.SetCapacity(info->mLiveDatabases.Length(),
|
||||
fallible))) {
|
||||
deleteOp->SetFailureCode(NS_ERROR_OUT_OF_MEMORY);
|
||||
} else {
|
||||
std::transform(info->mLiveDatabases.cbegin(),
|
||||
info->mLiveDatabases.cend(),
|
||||
MakeBackInserter(liveDatabases),
|
||||
[](const auto& aDatabase) -> SafeRefPtr<Database> {
|
||||
return {aDatabase, AcquireStrongRefFromRawPtr{}};
|
||||
});
|
||||
nsTArray<SafeRefPtr<Database>> liveDatabases;
|
||||
if (NS_WARN_IF(!liveDatabases.SetCapacity(info->mLiveDatabases.Length(),
|
||||
fallible))) {
|
||||
deleteOp->SetFailureCode(NS_ERROR_OUT_OF_MEMORY);
|
||||
} else {
|
||||
std::transform(info->mLiveDatabases.cbegin(),
|
||||
info->mLiveDatabases.cend(),
|
||||
MakeBackInserter(liveDatabases),
|
||||
[](const auto& aDatabase) -> SafeRefPtr<Database> {
|
||||
return {aDatabase, AcquireStrongRefFromRawPtr{}};
|
||||
});
|
||||
|
||||
#ifdef DEBUG
|
||||
// The code below should result in the deletion of |info|. Set to null
|
||||
// here to make sure we find invalid uses later.
|
||||
info = nullptr;
|
||||
// The code below should result in the deletion of |info|. Set to null
|
||||
// here to make sure we find invalid uses later.
|
||||
info = nullptr;
|
||||
#endif
|
||||
|
||||
for (const auto& database : liveDatabases) {
|
||||
database->Invalidate();
|
||||
}
|
||||
for (const auto& database : liveDatabases) {
|
||||
database->Invalidate();
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!gLiveDatabaseHashtable->Get(deleteOp->mDatabaseId));
|
||||
MOZ_ASSERT(!gLiveDatabaseHashtable->Get(deleteOp->mDatabaseId));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Загрузка…
Ссылка в новой задаче