mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 07:13:20 +00:00
Bug 1587258 - QM: Add support for creating specialized directory locks from existing directory locks; r=asuth
Differential Revision: https://phabricator.services.mozilla.com/D48657 --HG-- extra : moz-landing-system : lando
This commit is contained in:
parent
ff268df84b
commit
9dd55053d6
@ -677,6 +677,7 @@ class DirectoryLockImpl final : public DirectoryLock {
|
||||
// registraction/unregistration from updating origin access time, etc.
|
||||
const bool mInternal;
|
||||
|
||||
bool mRegistered;
|
||||
bool mInvalidated;
|
||||
|
||||
public:
|
||||
@ -706,13 +707,17 @@ class DirectoryLockImpl final : public DirectoryLock {
|
||||
|
||||
bool IsInternal() const { return mInternal; }
|
||||
|
||||
void SetRegistered(bool aRegistered) { mRegistered = aRegistered; }
|
||||
|
||||
bool ShouldUpdateLockTable() {
|
||||
return !mInternal &&
|
||||
mPersistenceType.Value() != PERSISTENCE_TYPE_PERSISTENT;
|
||||
}
|
||||
|
||||
bool Overlaps(const DirectoryLockImpl& aLock) const;
|
||||
|
||||
// Test whether this DirectoryLock needs to wait for the given lock.
|
||||
bool MustWaitFor(const DirectoryLockImpl& aLock);
|
||||
bool MustWaitFor(const DirectoryLockImpl& aLock) const;
|
||||
|
||||
void AddBlockingLock(DirectoryLockImpl* aLock) {
|
||||
AssertIsOnOwningThread();
|
||||
@ -747,12 +752,24 @@ class DirectoryLockImpl final : public DirectoryLock {
|
||||
|
||||
NS_INLINE_DECL_REFCOUNTING(DirectoryLockImpl, override)
|
||||
|
||||
void Log() override;
|
||||
already_AddRefed<DirectoryLock> Specialize(PersistenceType aPersistenceType,
|
||||
const nsACString& aGroup,
|
||||
const nsACString& aOrigin,
|
||||
Client::Type aClientType) const;
|
||||
|
||||
void Log() const;
|
||||
|
||||
private:
|
||||
~DirectoryLockImpl();
|
||||
};
|
||||
|
||||
const DirectoryLockImpl* GetDirectoryLockImpl(
|
||||
const DirectoryLock* aDirectoryLock) {
|
||||
MOZ_ASSERT(aDirectoryLock);
|
||||
|
||||
return static_cast<const DirectoryLockImpl*>(aDirectoryLock);
|
||||
}
|
||||
|
||||
class QuotaManager::Observer final : public nsIObserver {
|
||||
static Observer* sInstance;
|
||||
|
||||
@ -2667,6 +2684,15 @@ bool RecvShutdownQuotaManager() {
|
||||
* Directory lock
|
||||
******************************************************************************/
|
||||
|
||||
already_AddRefed<DirectoryLock> DirectoryLock::Specialize(
|
||||
PersistenceType aPersistenceType, const nsACString& aGroup,
|
||||
const nsACString& aOrigin, Client::Type aClientType) const {
|
||||
return GetDirectoryLockImpl(this)->Specialize(aPersistenceType, aGroup,
|
||||
aOrigin, aClientType);
|
||||
}
|
||||
|
||||
void DirectoryLock::Log() const { GetDirectoryLockImpl(this)->Log(); }
|
||||
|
||||
DirectoryLockImpl::DirectoryLockImpl(
|
||||
QuotaManager* aQuotaManager,
|
||||
const Nullable<PersistenceType>& aPersistenceType, const nsACString& aGroup,
|
||||
@ -2680,6 +2706,7 @@ DirectoryLockImpl::DirectoryLockImpl(
|
||||
mOpenListener(aOpenListener),
|
||||
mExclusive(aExclusive),
|
||||
mInternal(aInternal),
|
||||
mRegistered(false),
|
||||
mInvalidated(false) {
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(aQuotaManager);
|
||||
@ -2704,7 +2731,11 @@ DirectoryLockImpl::~DirectoryLockImpl() {
|
||||
|
||||
mBlocking.Clear();
|
||||
|
||||
mQuotaManager->UnregisterDirectoryLock(this);
|
||||
if (mRegistered) {
|
||||
mQuotaManager->UnregisterDirectoryLock(this);
|
||||
}
|
||||
|
||||
MOZ_ASSERT(!mRegistered);
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
@ -2716,29 +2747,24 @@ void DirectoryLockImpl::AssertIsOnOwningThread() const {
|
||||
|
||||
#endif // DEBUG
|
||||
|
||||
bool DirectoryLockImpl::MustWaitFor(const DirectoryLockImpl& aExistingLock) {
|
||||
bool DirectoryLockImpl::Overlaps(const DirectoryLockImpl& aLock) const {
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
// Waiting is never required if the ops in comparison represent shared locks.
|
||||
if (!aExistingLock.mExclusive && !mExclusive) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the persistence types don't overlap, the op can proceed.
|
||||
if (!aExistingLock.mPersistenceType.IsNull() && !mPersistenceType.IsNull() &&
|
||||
aExistingLock.mPersistenceType.Value() != mPersistenceType.Value()) {
|
||||
if (!aLock.mPersistenceType.IsNull() && !mPersistenceType.IsNull() &&
|
||||
aLock.mPersistenceType.Value() != mPersistenceType.Value()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the origin scopes don't overlap, the op can proceed.
|
||||
bool match = aExistingLock.mOriginScope.Matches(mOriginScope);
|
||||
bool match = aLock.mOriginScope.Matches(mOriginScope);
|
||||
if (!match) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// If the client types don't overlap, the op can proceed.
|
||||
if (!aExistingLock.mClientType.IsNull() && !mClientType.IsNull() &&
|
||||
aExistingLock.mClientType.Value() != mClientType.Value()) {
|
||||
if (!aLock.mClientType.IsNull() && !mClientType.IsNull() &&
|
||||
aLock.mClientType.Value() != mClientType.Value()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -2747,6 +2773,18 @@ bool DirectoryLockImpl::MustWaitFor(const DirectoryLockImpl& aExistingLock) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool DirectoryLockImpl::MustWaitFor(const DirectoryLockImpl& aLock) const {
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
// Waiting is never required if the ops in comparison represent shared locks.
|
||||
if (!aLock.mExclusive && !mExclusive) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Wait if the ops overlap.
|
||||
return Overlaps(aLock);
|
||||
}
|
||||
|
||||
void DirectoryLockImpl::NotifyOpenListener() {
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(mQuotaManager);
|
||||
@ -2763,7 +2801,59 @@ void DirectoryLockImpl::NotifyOpenListener() {
|
||||
mQuotaManager->RemovePendingDirectoryLock(this);
|
||||
}
|
||||
|
||||
void DirectoryLockImpl::Log() {
|
||||
already_AddRefed<DirectoryLock> DirectoryLockImpl::Specialize(
|
||||
PersistenceType aPersistenceType, const nsACString& aGroup,
|
||||
const nsACString& aOrigin, Client::Type aClientType) const {
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(aPersistenceType != PERSISTENCE_TYPE_INVALID);
|
||||
MOZ_ASSERT(!aGroup.IsEmpty());
|
||||
MOZ_ASSERT(!aOrigin.IsEmpty());
|
||||
MOZ_ASSERT(aClientType < Client::TypeMax());
|
||||
MOZ_ASSERT(!mOpenListener);
|
||||
MOZ_ASSERT(mBlockedOn.IsEmpty());
|
||||
|
||||
if (NS_WARN_IF(mExclusive)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
RefPtr<DirectoryLockImpl> lock = new DirectoryLockImpl(
|
||||
mQuotaManager, Nullable<PersistenceType>(aPersistenceType), aGroup,
|
||||
OriginScope::FromOrigin(aOrigin), Nullable<Client::Type>(aClientType),
|
||||
/* aExclusive */ false, mInternal, /* aOpenListener */ nullptr);
|
||||
|
||||
if (NS_WARN_IF(!Overlaps(*lock))) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
for (uint32_t index = mQuotaManager->mDirectoryLocks.Length(); index > 0;
|
||||
index--) {
|
||||
DirectoryLockImpl* existingLock = mQuotaManager->mDirectoryLocks[index - 1];
|
||||
if (existingLock != this && !existingLock->MustWaitFor(*this)) {
|
||||
MOZ_ASSERT(!existingLock->MustWaitFor(*lock));
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
for (const auto& blockedLock : mBlocking) {
|
||||
MOZ_ASSERT(blockedLock);
|
||||
|
||||
if (blockedLock->MustWaitFor(*lock)) {
|
||||
lock->AddBlockingLock(blockedLock);
|
||||
blockedLock->AddBlockedOnLock(lock);
|
||||
}
|
||||
}
|
||||
|
||||
mQuotaManager->RegisterDirectoryLock(lock);
|
||||
|
||||
if (mInvalidated) {
|
||||
lock->Invalidate();
|
||||
}
|
||||
|
||||
return lock.forget();
|
||||
}
|
||||
|
||||
void DirectoryLockImpl::Log() const {
|
||||
AssertIsOnOwningThread();
|
||||
|
||||
if (!QM_LOG_TEST()) {
|
||||
@ -3525,6 +3615,8 @@ void QuotaManager::RegisterDirectoryLock(DirectoryLockImpl* aLock) {
|
||||
}
|
||||
array->AppendElement(aLock);
|
||||
}
|
||||
|
||||
aLock->SetRegistered(true);
|
||||
}
|
||||
|
||||
void QuotaManager::UnregisterDirectoryLock(DirectoryLockImpl* aLock) {
|
||||
@ -3558,6 +3650,8 @@ void QuotaManager::UnregisterDirectoryLock(DirectoryLockImpl* aLock) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
aLock->SetRegistered(false);
|
||||
}
|
||||
|
||||
void QuotaManager::RemovePendingDirectoryLock(DirectoryLockImpl* aLock) {
|
||||
|
@ -63,7 +63,12 @@ class DirectoryLock : public RefCountedObject {
|
||||
friend class DirectoryLockImpl;
|
||||
|
||||
public:
|
||||
virtual void Log() = 0;
|
||||
already_AddRefed<DirectoryLock> Specialize(PersistenceType aPersistenceType,
|
||||
const nsACString& aGroup,
|
||||
const nsACString& aOrigin,
|
||||
Client::Type aClientType) const;
|
||||
|
||||
void Log() const;
|
||||
|
||||
private:
|
||||
DirectoryLock() {}
|
||||
|
Loading…
Reference in New Issue
Block a user