Bug 1690025 - Split public DirectoryLock class into a hierarchy of public classes; r=dom-storage-reviewers,sg

Differential Revision: https://phabricator.services.mozilla.com/D104360
This commit is contained in:
Jan Varga 2021-02-09 15:01:54 +00:00
parent 0916876268
commit eee089ae3d
5 changed files with 122 additions and 128 deletions

View File

@ -70,7 +70,6 @@
#include "mozilla/Variant.h"
#include "mozilla/dom/FlippedOnce.h"
#include "mozilla/dom/LocalStorageCommon.h"
#include "mozilla/dom/Nullable.h"
#include "mozilla/dom/StorageActivityService.h"
#include "mozilla/dom/StorageDBUpdater.h"
#include "mozilla/dom/StorageTypeBinding.h"
@ -718,19 +717,6 @@ Result<mozilla::Ok, nsresult> CollectEachFileEntry(
} // namespace
const DirectoryLockImpl* AsDirectoryLockImpl(
const DirectoryLock* aDirectoryLock) {
MOZ_ASSERT(aDirectoryLock);
return static_cast<const DirectoryLockImpl*>(aDirectoryLock);
}
DirectoryLockImpl* AsDirectoryLockImpl(DirectoryLock* aDirectoryLock) {
MOZ_ASSERT(aDirectoryLock);
return static_cast<DirectoryLockImpl*>(aDirectoryLock);
}
class QuotaManager::Observer final : public nsIObserver {
static Observer* sInstance;
@ -999,7 +985,7 @@ class CollectOriginsHelper final : public Runnable {
CondVar mCondVar;
// The members below are protected by mMutex.
nsTArray<RefPtr<DirectoryLockImpl>> mLocks;
nsTArray<RefPtr<OriginDirectoryLock>> mLocks;
uint64_t mSizeToBeFreed;
bool mWaiting;
@ -1009,7 +995,7 @@ class CollectOriginsHelper final : public Runnable {
// Blocks the current thread until origins are collected on the main thread.
// The returned value contains an aggregate size of those origins.
int64_t BlockAndReturnOriginsForEviction(
nsTArray<RefPtr<DirectoryLockImpl>>& aLocks);
nsTArray<RefPtr<OriginDirectoryLock>>& aLocks);
private:
~CollectOriginsHelper() = default;
@ -1135,11 +1121,11 @@ class OriginOperationBase : public BackgroundThreadObject, public Runnable {
};
class FinalizeOriginEvictionOp : public OriginOperationBase {
nsTArray<RefPtr<DirectoryLockImpl>> mLocks;
nsTArray<RefPtr<OriginDirectoryLock>> mLocks;
public:
FinalizeOriginEvictionOp(nsIEventTarget* aBackgroundThread,
nsTArray<RefPtr<DirectoryLockImpl>>&& aLocks)
nsTArray<RefPtr<OriginDirectoryLock>>&& aLocks)
: OriginOperationBase(aBackgroundThread), mLocks(std::move(aLocks)) {
MOZ_ASSERT(!NS_IsMainThread());
}
@ -2631,42 +2617,6 @@ bool RecvShutdownQuotaManager() {
return true;
}
/*******************************************************************************
* Directory lock
******************************************************************************/
int64_t DirectoryLock::Id() const { return AsDirectoryLockImpl(this)->Id(); }
PersistenceType DirectoryLock::GetPersistenceType() const {
return AsDirectoryLockImpl(this)->GetPersistenceType();
}
quota::GroupAndOrigin DirectoryLock::GroupAndOrigin() const {
return AsDirectoryLockImpl(this)->GroupAndOrigin();
}
const nsACString& DirectoryLock::Origin() const {
return AsDirectoryLockImpl(this)->Origin();
}
Client::Type DirectoryLock::ClientType() const {
return AsDirectoryLockImpl(this)->ClientType();
}
void DirectoryLock::Acquire(RefPtr<OpenDirectoryListener> aOpenListener) {
AsDirectoryLockImpl(this)->Acquire(std::move(aOpenListener));
}
RefPtr<DirectoryLock> DirectoryLock::Specialize(
PersistenceType aPersistenceType,
const quota::GroupAndOrigin& aGroupAndOrigin,
Client::Type aClientType) const {
return AsDirectoryLockImpl(this)->Specialize(aPersistenceType,
aGroupAndOrigin, aClientType);
}
void DirectoryLock::Log() const { AsDirectoryLockImpl(this)->Log(); }
QuotaManager::Observer* QuotaManager::Observer::sInstance = nullptr;
// static
@ -3062,7 +3012,7 @@ bool QuotaObject::LockedMaybeUpdateSize(int64_t aSize, bool aTruncate) {
if (newTemporaryStorageUsage > quotaManager->mTemporaryStorageLimit) {
// This will block the thread without holding the lock while waitting.
AutoTArray<RefPtr<DirectoryLockImpl>, 10> locks;
AutoTArray<RefPtr<OriginDirectoryLock>, 10> locks;
uint64_t sizeToBeFreed;
if (IsOnBackgroundThread()) {
@ -3089,7 +3039,7 @@ bool QuotaObject::LockedMaybeUpdateSize(int64_t aSize, bool aTruncate) {
{
MutexAutoUnlock autoUnlock(quotaManager->mQuotaMutex);
for (RefPtr<DirectoryLockImpl>& lock : locks) {
for (const auto& lock : locks) {
quotaManager->DeleteFilesForOrigin(lock->GetPersistenceType(),
lock->Origin());
}
@ -3099,7 +3049,7 @@ bool QuotaObject::LockedMaybeUpdateSize(int64_t aSize, bool aTruncate) {
NS_ASSERTION(mOriginInfo, "How come?!");
for (DirectoryLockImpl* lock : locks) {
for (const auto& lock : locks) {
MOZ_ASSERT(!(lock->GetPersistenceType() == groupInfo->mPersistenceType &&
lock->Origin() == mOriginInfo->mOrigin),
"Deleted itself!");
@ -3394,7 +3344,7 @@ void QuotaManager::RemovePendingDirectoryLock(DirectoryLockImpl& aLock) {
}
uint64_t QuotaManager::CollectOriginsForEviction(
uint64_t aMinSizeToBeFreed, nsTArray<RefPtr<DirectoryLockImpl>>& aLocks) {
uint64_t aMinSizeToBeFreed, nsTArray<RefPtr<OriginDirectoryLock>>& aLocks) {
AssertIsOnOwningThread();
MOZ_ASSERT(aLocks.IsEmpty());
@ -3520,11 +3470,11 @@ uint64_t QuotaManager::CollectOriginsForEviction(
// operations for them will be delayed (until origin eviction is finalized).
for (const auto& originInfo : inactiveOrigins) {
RefPtr<DirectoryLockImpl> lock = DirectoryLockImpl::CreateForEviction(
auto lock = DirectoryLockImpl::CreateForEviction(
WrapNotNullUnchecked(this), originInfo->mGroupInfo->mPersistenceType,
GroupAndOrigin{originInfo->mGroupInfo->mGroup, originInfo->mOrigin});
lock->Acquire();
lock->AcquireImmediately();
aLocks.AppendElement(lock.forget());
}
@ -5951,7 +5901,7 @@ nsresult QuotaManager::EnsureStorageIsInitialized() {
return NS_OK;
}
RefPtr<DirectoryLock> QuotaManager::CreateDirectoryLock(
RefPtr<ClientDirectoryLock> QuotaManager::CreateDirectoryLock(
PersistenceType aPersistenceType, const GroupAndOrigin& aGroupAndOrigin,
Client::Type aClientType, bool aExclusive) {
AssertIsOnOwningThread();
@ -5960,7 +5910,7 @@ RefPtr<DirectoryLock> QuotaManager::CreateDirectoryLock(
aGroupAndOrigin, aClientType, aExclusive);
}
RefPtr<DirectoryLock> QuotaManager::CreateDirectoryLockInternal(
RefPtr<UniversalDirectoryLock> QuotaManager::CreateDirectoryLockInternal(
const Nullable<PersistenceType>& aPersistenceType,
const OriginScope& aOriginScope, const Nullable<Client::Type>& aClientType,
bool aExclusive) {
@ -6594,7 +6544,7 @@ Result<PrincipalInfo, nsresult> QuotaManager::ParseOrigin(
void QuotaManager::InvalidateQuotaCache() { gInvalidateQuotaCache = true; }
uint64_t QuotaManager::LockedCollectOriginsForEviction(
uint64_t aMinSizeToBeFreed, nsTArray<RefPtr<DirectoryLockImpl>>& aLocks) {
uint64_t aMinSizeToBeFreed, nsTArray<RefPtr<OriginDirectoryLock>>& aLocks) {
mQuotaMutex.AssertCurrentThreadOwns();
RefPtr<CollectOriginsHelper> helper =
@ -6878,7 +6828,7 @@ void QuotaManager::DeleteFilesForOrigin(PersistenceType aPersistenceType,
}
void QuotaManager::FinalizeOriginEviction(
nsTArray<RefPtr<DirectoryLockImpl>>&& aLocks) {
nsTArray<RefPtr<OriginDirectoryLock>>&& aLocks) {
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
RefPtr<FinalizeOriginEvictionOp> op =
@ -7220,7 +7170,7 @@ CollectOriginsHelper::CollectOriginsHelper(mozilla::Mutex& aMutex,
}
int64_t CollectOriginsHelper::BlockAndReturnOriginsForEviction(
nsTArray<RefPtr<DirectoryLockImpl>>& aLocks) {
nsTArray<RefPtr<OriginDirectoryLock>>& aLocks) {
MOZ_ASSERT(!NS_IsMainThread(), "Wrong thread!");
mMutex.AssertCurrentThreadOwns();
@ -7241,7 +7191,7 @@ CollectOriginsHelper::Run() {
// We use extra stack vars here to avoid race detector warnings (the same
// memory accessed with and without the lock held).
nsTArray<RefPtr<DirectoryLockImpl>> locks;
nsTArray<RefPtr<OriginDirectoryLock>> locks;
uint64_t sizeToBeFreed =
quotaManager->CollectOriginsForEviction(mMinSizeToBeFreed, locks);
@ -7410,7 +7360,7 @@ nsresult FinalizeOriginEvictionOp::DoDirectoryWork(
AUTO_PROFILER_LABEL("FinalizeOriginEvictionOp::DoDirectoryWork", OTHER);
for (RefPtr<DirectoryLockImpl>& lock : mLocks) {
for (const auto& lock : mLocks) {
aQuotaManager.OriginClearCompleted(
lock->GetPersistenceType(), lock->Origin(), Nullable<Client::Type>());
}

View File

@ -7,50 +7,81 @@
#ifndef DOM_QUOTA_DIRECTORYLOCK_H_
#define DOM_QUOTA_DIRECTORYLOCK_H_
#include "mozilla/dom/Nullable.h"
#include "mozilla/dom/quota/Client.h"
#include "mozilla/dom/quota/PersistenceType.h"
namespace mozilla::dom::quota {
class ClientDirectoryLock;
struct GroupAndOrigin;
class OpenDirectoryListener;
class NS_NO_VTABLE RefCountedObject {
// Basic directory lock interface shared by all other directory lock classes.
// The class must contain pure virtual functions only to avoid problems with
// multiple inheritance.
class NS_NO_VTABLE DirectoryLock {
public:
NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING
virtual int64_t Id() const = 0;
virtual void Acquire(RefPtr<OpenDirectoryListener> aOpenListener) = 0;
virtual void AcquireImmediately() = 0;
// XXX Move to the UniversalDirectoryLock class.
virtual RefPtr<ClientDirectoryLock> Specialize(
PersistenceType aPersistenceType, const GroupAndOrigin& aGroupAndOrigin,
Client::Type aClientType) const = 0;
virtual void Log() const = 0;
};
class DirectoryLock : public RefCountedObject {
friend class DirectoryLockImpl;
// A directory lock specialized for a given origin directory.
class NS_NO_VTABLE OriginDirectoryLock : public DirectoryLock {
public:
int64_t Id() const;
// 'Get' prefix is to avoid name collisions with the enum
PersistenceType GetPersistenceType() const;
virtual PersistenceType GetPersistenceType() const = 0;
quota::GroupAndOrigin GroupAndOrigin() const;
virtual quota::GroupAndOrigin GroupAndOrigin() const = 0;
const nsACString& Origin() const;
Client::Type ClientType() const;
void Acquire(RefPtr<OpenDirectoryListener> aOpenListener);
RefPtr<DirectoryLock> Specialize(PersistenceType aPersistenceType,
const quota::GroupAndOrigin& aGroupAndOrigin,
Client::Type aClientType) const;
void Log() const;
private:
DirectoryLock() = default;
~DirectoryLock() = default;
virtual const nsACString& Origin() const = 0;
};
class NS_NO_VTABLE OpenDirectoryListener : public RefCountedObject {
// A directory lock specialized for a given client directory (inside an origin
// directory).
class NS_NO_VTABLE ClientDirectoryLock : public OriginDirectoryLock {
public:
virtual Client::Type ClientType() const = 0;
};
// A directory lock for universal use. A universal lock can handle any possible
// combination of nullable persistence type, origin scope and nullable client
// type.
//
// For example, if the persistence type is set to null, origin scope is null
// and the client type is set to Client::IDB, then the lock will cover
// <profile>/storage/*/*/idb
//
// If no property is set, then the lock will cover the entire storage directory
// and its subdirectories.
class UniversalDirectoryLock : public DirectoryLock {
public:
// XXX Rename to NullablePersistenceTypeRef.
virtual const Nullable<PersistenceType>& NullablePersistenceType() const = 0;
// XXX Rename to OriginScopeRef.
virtual const OriginScope& GetOriginScope() const = 0;
// XXX Rename to NullableClientTypeRef.
virtual const Nullable<Client::Type>& NullableClientType() const = 0;
};
class NS_NO_VTABLE OpenDirectoryListener {
public:
NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING
virtual void DirectoryLockAcquired(DirectoryLock* aLock) = 0;
virtual void DirectoryLockFailed() = 0;

View File

@ -108,7 +108,8 @@ void DirectoryLockImpl::NotifyOpenListener() {
if (mInvalidated) {
(*mOpenListener)->DirectoryLockFailed();
} else {
(*mOpenListener)->DirectoryLockAcquired(this);
(*mOpenListener)
->DirectoryLockAcquired(static_cast<UniversalDirectoryLock*>(this));
}
mOpenListener.destroy();
@ -177,7 +178,7 @@ void DirectoryLockImpl::Acquire(RefPtr<OpenDirectoryListener> aOpenListener) {
mQuotaManager->AbortOperationsForLocks(lockIds);
}
void DirectoryLockImpl::Acquire() {
void DirectoryLockImpl::AcquireImmediately() {
AssertIsOnOwningThread();
#ifdef DEBUG
@ -190,7 +191,7 @@ void DirectoryLockImpl::Acquire() {
mQuotaManager->RegisterDirectoryLock(*this);
}
RefPtr<DirectoryLock> DirectoryLockImpl::Specialize(
RefPtr<ClientDirectoryLock> DirectoryLockImpl::Specialize(
PersistenceType aPersistenceType,
const quota::GroupAndOrigin& aGroupAndOrigin,
Client::Type aClientType) const {

View File

@ -17,7 +17,8 @@ namespace mozilla::dom::quota {
enum class ShouldUpdateLockIdTableFlag { No, Yes };
class DirectoryLockImpl final : public DirectoryLock {
class DirectoryLockImpl final : public ClientDirectoryLock,
public UniversalDirectoryLock {
const NotNull<RefPtr<QuotaManager>> mQuotaManager;
const Nullable<PersistenceType> mPersistenceType;
@ -53,7 +54,7 @@ class DirectoryLockImpl final : public DirectoryLock {
bool aInternal,
ShouldUpdateLockIdTableFlag aShouldUpdateLockIdTableFlag);
static RefPtr<DirectoryLockImpl> Create(
static RefPtr<ClientDirectoryLock> Create(
MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
PersistenceType aPersistenceType,
const quota::GroupAndOrigin& aGroupAndOrigin, Client::Type aClientType,
@ -66,7 +67,7 @@ class DirectoryLockImpl final : public DirectoryLock {
ShouldUpdateLockIdTableFlag::Yes);
}
static RefPtr<DirectoryLockImpl> CreateForEviction(
static RefPtr<OriginDirectoryLock> CreateForEviction(
MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
PersistenceType aPersistenceType,
const quota::GroupAndOrigin& aGroupAndOrigin) {
@ -82,7 +83,7 @@ class DirectoryLockImpl final : public DirectoryLock {
ShouldUpdateLockIdTableFlag::No);
}
static RefPtr<DirectoryLockImpl> CreateInternal(
static RefPtr<UniversalDirectoryLock> CreateInternal(
MovingNotNull<RefPtr<QuotaManager>> aQuotaManager,
const Nullable<PersistenceType>& aPersistenceType,
const OriginScope& aOriginScope,
@ -100,16 +101,6 @@ class DirectoryLockImpl final : public DirectoryLock {
}
#endif
const Nullable<PersistenceType>& NullablePersistenceType() const {
return mPersistenceType;
}
const OriginScope& GetOriginScope() const { return mOriginScope; }
const Nullable<Client::Type>& NullableClientType() const {
return mClientType;
}
bool IsInternal() const { return mInternal; }
void SetRegistered(bool aRegistered) { mRegistered = aRegistered; }
@ -170,47 +161,64 @@ class DirectoryLockImpl final : public DirectoryLock {
mInvalidated.EnsureFlipped();
}
NS_INLINE_DECL_REFCOUNTING(DirectoryLockImpl, override)
// DirectoryLock interface
int64_t Id() const { return mId; }
NS_INLINE_DECL_REFCOUNTING(DirectoryLockImpl, override)
PersistenceType GetPersistenceType() const {
int64_t Id() const override { return mId; }
void Acquire(RefPtr<OpenDirectoryListener> aOpenListener) override;
void AcquireImmediately() override;
RefPtr<ClientDirectoryLock> Specialize(
PersistenceType aPersistenceType,
const quota::GroupAndOrigin& aGroupAndOrigin,
Client::Type aClientType) const override;
void Log() const override;
// OriginDirectoryLock interface
PersistenceType GetPersistenceType() const override {
MOZ_DIAGNOSTIC_ASSERT(!mPersistenceType.IsNull());
return mPersistenceType.Value();
}
quota::GroupAndOrigin GroupAndOrigin() const {
quota::GroupAndOrigin GroupAndOrigin() const override {
MOZ_DIAGNOSTIC_ASSERT(!mGroup.IsEmpty());
return quota::GroupAndOrigin{mGroup, nsCString(Origin())};
}
const nsACString& Origin() const {
const nsACString& Origin() const override {
MOZ_DIAGNOSTIC_ASSERT(mOriginScope.IsOrigin());
MOZ_DIAGNOSTIC_ASSERT(!mOriginScope.GetOrigin().IsEmpty());
return mOriginScope.GetOrigin();
}
Client::Type ClientType() const {
// ClientDirectoryLock interface
Client::Type ClientType() const override {
MOZ_DIAGNOSTIC_ASSERT(!mClientType.IsNull());
MOZ_DIAGNOSTIC_ASSERT(mClientType.Value() < Client::TypeMax());
return mClientType.Value();
}
void Acquire(RefPtr<OpenDirectoryListener> aOpenListener);
// UniversalDirectoryLock interface
void Acquire();
const Nullable<PersistenceType>& NullablePersistenceType() const override {
return mPersistenceType;
}
RefPtr<DirectoryLock> Specialize(PersistenceType aPersistenceType,
const quota::GroupAndOrigin& aGroupAndOrigin,
Client::Type aClientType) const;
const OriginScope& GetOriginScope() const override { return mOriginScope; }
void Log() const;
const Nullable<Client::Type>& NullableClientType() const override {
return mClientType;
}
private:
~DirectoryLockImpl();

View File

@ -61,13 +61,15 @@ class PrincipalInfo;
namespace mozilla::dom::quota {
class ClientUsageArray;
class DirectoryLock;
class ClientDirectoryLock;
class DirectoryLockImpl;
class GroupInfo;
class GroupInfoPair;
class OriginDirectoryLock;
class OriginInfo;
class OriginScope;
class QuotaObject;
class UniversalDirectoryLock;
class QuotaManager final : public BackgroundThreadObject {
friend class DirectoryLockImpl;
@ -253,19 +255,20 @@ class QuotaManager final : public BackgroundThreadObject {
// Unlocking is simply done by dropping all references to the lock object.
// In other words, protection which the lock represents dies with the lock
// object itself.
RefPtr<DirectoryLock> CreateDirectoryLock(
RefPtr<ClientDirectoryLock> CreateDirectoryLock(
PersistenceType aPersistenceType, const GroupAndOrigin& aGroupAndOrigin,
Client::Type aClientType, bool aExclusive);
// XXX RemoveMe once bug 1170279 gets fixed.
RefPtr<DirectoryLock> CreateDirectoryLockInternal(
RefPtr<UniversalDirectoryLock> CreateDirectoryLockInternal(
const Nullable<PersistenceType>& aPersistenceType,
const OriginScope& aOriginScope,
const Nullable<Client::Type>& aClientType, bool aExclusive);
// Collect inactive and the least recently used origins.
uint64_t CollectOriginsForEviction(
uint64_t aMinSizeToBeFreed, nsTArray<RefPtr<DirectoryLockImpl>>& aLocks);
uint64_t aMinSizeToBeFreed,
nsTArray<RefPtr<OriginDirectoryLock>>& aLocks);
/**
* Helper method to invoke the provided predicate on all "pending" OriginInfo
@ -433,7 +436,8 @@ class QuotaManager final : public BackgroundThreadObject {
void RemovePendingDirectoryLock(DirectoryLockImpl& aLock);
uint64_t LockedCollectOriginsForEviction(
uint64_t aMinSizeToBeFreed, nsTArray<RefPtr<DirectoryLockImpl>>& aLocks);
uint64_t aMinSizeToBeFreed,
nsTArray<RefPtr<OriginDirectoryLock>>& aLocks);
void LockedRemoveQuotaForOrigin(PersistenceType aPersistenceType,
const GroupAndOrigin& aGroupAndOrigin);
@ -519,7 +523,7 @@ class QuotaManager final : public BackgroundThreadObject {
void DeleteFilesForOrigin(PersistenceType aPersistenceType,
const nsACString& aOrigin);
void FinalizeOriginEviction(nsTArray<RefPtr<DirectoryLockImpl>>&& aLocks);
void FinalizeOriginEviction(nsTArray<RefPtr<OriginDirectoryLock>>&& aLocks);
void ReleaseIOThreadObjects() {
AssertIsOnIOThread();