mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-28 07:13:20 +00:00
Bug 1685677 - Extract functions from CheckTemporaryStorageLimits and rename it to CleanupTemporaryStorage. r=dom-workers-and-storage-reviewers,janv
Extracts parts of CheckTemporaryStorageLimits into the following new private member functions of QuotaManager: * LockedGetOriginInfosExceedingGroupLimit * LockedGetOriginInfosExceedingGlobalLimit * GetOriginInfosExceedingLimits * ClearOrigins Differential Revision: https://phabricator.services.mozilla.com/D101145
This commit is contained in:
parent
b0327ecf3c
commit
0da4951ba0
@ -952,13 +952,13 @@ class OriginInfo final {
|
||||
|
||||
class OriginInfoLRUComparator {
|
||||
public:
|
||||
bool Equals(const NotNull<RefPtr<OriginInfo>>& a,
|
||||
const NotNull<RefPtr<OriginInfo>>& b) const {
|
||||
bool Equals(const NotNull<RefPtr<const OriginInfo>>& a,
|
||||
const NotNull<RefPtr<const OriginInfo>>& b) const {
|
||||
return a->LockedAccessTime() == b->LockedAccessTime();
|
||||
}
|
||||
|
||||
bool LessThan(const NotNull<RefPtr<OriginInfo>>& a,
|
||||
const NotNull<RefPtr<OriginInfo>>& b) const {
|
||||
bool LessThan(const NotNull<RefPtr<const OriginInfo>>& a,
|
||||
const NotNull<RefPtr<const OriginInfo>>& b) const {
|
||||
return a->LockedAccessTime() < b->LockedAccessTime();
|
||||
}
|
||||
};
|
||||
@ -3783,8 +3783,8 @@ uint64_t QuotaManager::CollectOriginsForEviction(
|
||||
static void GetInactiveOriginInfos(
|
||||
const nsTArray<NotNull<RefPtr<OriginInfo>>>& aOriginInfos,
|
||||
const nsTArray<NotNull<DirectoryLockImpl*>>& aLocks,
|
||||
nsTArray<NotNull<RefPtr<OriginInfo>>>& aInactiveOriginInfos) {
|
||||
for (const NotNull<RefPtr<OriginInfo>>& originInfo : aOriginInfos) {
|
||||
OriginInfosFlatTraversable& aInactiveOriginInfos) {
|
||||
for (const auto& originInfo : aOriginInfos) {
|
||||
MOZ_ASSERT(originInfo->mGroupInfo->mPersistenceType !=
|
||||
PERSISTENCE_TYPE_PERSISTENT);
|
||||
|
||||
@ -3832,7 +3832,7 @@ uint64_t QuotaManager::CollectOriginsForEviction(
|
||||
}
|
||||
}
|
||||
|
||||
nsTArray<NotNull<RefPtr<OriginInfo>>> inactiveOrigins;
|
||||
OriginInfosFlatTraversable inactiveOrigins;
|
||||
|
||||
// Enumerate and process inactive origins. This must be protected by the
|
||||
// mutex.
|
||||
@ -6549,7 +6549,7 @@ nsresult QuotaManager::EnsureTemporaryStorageIsInitialized() {
|
||||
mTemporaryStorageLimit = GetTemporaryStorageLimit(
|
||||
/* aAvailableSpaceBytes */ diskSpaceAvailable + mTemporaryStorageUsage);
|
||||
|
||||
CheckTemporaryStorageLimits();
|
||||
CleanupTemporaryStorage();
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
@ -7091,150 +7091,195 @@ already_AddRefed<OriginInfo> QuotaManager::LockedGetOriginInfo(
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void QuotaManager::CheckTemporaryStorageLimits() {
|
||||
AssertIsOnIOThread();
|
||||
QuotaManager::OriginInfosFlatTraversable
|
||||
QuotaManager::LockedGetOriginInfosExceedingGroupLimit() const {
|
||||
mQuotaMutex.AssertCurrentThreadOwns();
|
||||
|
||||
const auto doomedOrigins = [this] {
|
||||
const auto doomedOriginInfos = [this] {
|
||||
nsTArray<NotNull<RefPtr<OriginInfo>>> doomedOriginInfos;
|
||||
MutexAutoLock lock(mQuotaMutex);
|
||||
OriginInfosFlatTraversable originInfos;
|
||||
|
||||
for (const auto& entry : mGroupInfoPairs) {
|
||||
const auto& pair = entry.GetData();
|
||||
for (const auto& entry : mGroupInfoPairs) {
|
||||
const auto& pair = entry.GetData();
|
||||
|
||||
MOZ_ASSERT(!entry.GetKey().IsEmpty());
|
||||
MOZ_ASSERT(pair);
|
||||
MOZ_ASSERT(!entry.GetKey().IsEmpty());
|
||||
MOZ_ASSERT(pair);
|
||||
|
||||
uint64_t groupUsage = 0;
|
||||
uint64_t groupUsage = 0;
|
||||
|
||||
RefPtr<GroupInfo> temporaryGroupInfo =
|
||||
pair->LockedGetGroupInfo(PERSISTENCE_TYPE_TEMPORARY);
|
||||
if (temporaryGroupInfo) {
|
||||
groupUsage += temporaryGroupInfo->mUsage;
|
||||
}
|
||||
const RefPtr<GroupInfo> temporaryGroupInfo =
|
||||
pair->LockedGetGroupInfo(PERSISTENCE_TYPE_TEMPORARY);
|
||||
if (temporaryGroupInfo) {
|
||||
groupUsage += temporaryGroupInfo->mUsage;
|
||||
}
|
||||
|
||||
RefPtr<GroupInfo> defaultGroupInfo =
|
||||
pair->LockedGetGroupInfo(PERSISTENCE_TYPE_DEFAULT);
|
||||
if (defaultGroupInfo) {
|
||||
groupUsage += defaultGroupInfo->mUsage;
|
||||
}
|
||||
const RefPtr<GroupInfo> defaultGroupInfo =
|
||||
pair->LockedGetGroupInfo(PERSISTENCE_TYPE_DEFAULT);
|
||||
if (defaultGroupInfo) {
|
||||
groupUsage += defaultGroupInfo->mUsage;
|
||||
}
|
||||
|
||||
if (groupUsage > 0) {
|
||||
QuotaManager* quotaManager = QuotaManager::Get();
|
||||
MOZ_ASSERT(quotaManager, "Shouldn't be null!");
|
||||
if (groupUsage > 0) {
|
||||
QuotaManager* quotaManager = QuotaManager::Get();
|
||||
MOZ_ASSERT(quotaManager, "Shouldn't be null!");
|
||||
|
||||
if (groupUsage > quotaManager->GetGroupLimit()) {
|
||||
nsTArray<NotNull<RefPtr<OriginInfo>>> originInfos;
|
||||
if (temporaryGroupInfo) {
|
||||
originInfos.AppendElements(temporaryGroupInfo->mOriginInfos);
|
||||
}
|
||||
if (defaultGroupInfo) {
|
||||
originInfos.AppendElements(defaultGroupInfo->mOriginInfos);
|
||||
}
|
||||
originInfos.Sort(OriginInfoLRUComparator());
|
||||
|
||||
for (uint32_t i = 0; i < originInfos.Length(); i++) {
|
||||
const NotNull<RefPtr<OriginInfo>>& originInfo = originInfos[i];
|
||||
if (originInfo->LockedPersisted()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
doomedOriginInfos.AppendElement(originInfo);
|
||||
groupUsage -= originInfo->LockedUsage();
|
||||
|
||||
if (groupUsage <= quotaManager->GetGroupLimit()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (groupUsage > quotaManager->GetGroupLimit()) {
|
||||
const auto allOriginInfosLRUSorted = [&temporaryGroupInfo,
|
||||
&defaultGroupInfo] {
|
||||
OriginInfosFlatTraversable originInfos;
|
||||
if (temporaryGroupInfo) {
|
||||
originInfos.AppendElements(temporaryGroupInfo->mOriginInfos);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (defaultGroupInfo) {
|
||||
originInfos.AppendElements(defaultGroupInfo->mOriginInfos);
|
||||
}
|
||||
originInfos.Sort(OriginInfoLRUComparator());
|
||||
return originInfos;
|
||||
}();
|
||||
|
||||
uint64_t usage = std::accumulate(
|
||||
doomedOriginInfos.cbegin(), doomedOriginInfos.cend(), uint64_t(0),
|
||||
[](uint64_t oldValue, const auto& originInfo) {
|
||||
return oldValue + originInfo->LockedUsage();
|
||||
});
|
||||
|
||||
if (mTemporaryStorageUsage - usage > mTemporaryStorageLimit) {
|
||||
nsTArray<NotNull<RefPtr<OriginInfo>>> originInfos;
|
||||
|
||||
for (const auto& entry : mGroupInfoPairs) {
|
||||
const auto& pair = entry.GetData();
|
||||
|
||||
MOZ_ASSERT(!entry.GetKey().IsEmpty());
|
||||
MOZ_ASSERT(pair);
|
||||
|
||||
RefPtr<GroupInfo> groupInfo =
|
||||
pair->LockedGetGroupInfo(PERSISTENCE_TYPE_TEMPORARY);
|
||||
if (groupInfo) {
|
||||
originInfos.AppendElements(groupInfo->mOriginInfos);
|
||||
for (const auto& originInfo : allOriginInfosLRUSorted) {
|
||||
// XXX We can remove these before sorting and then just truncate the
|
||||
// existing array at the right point.
|
||||
if (originInfo->LockedPersisted()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
groupInfo = pair->LockedGetGroupInfo(PERSISTENCE_TYPE_DEFAULT);
|
||||
if (groupInfo) {
|
||||
originInfos.AppendElements(groupInfo->mOriginInfos);
|
||||
}
|
||||
}
|
||||
originInfos.AppendElement(originInfo);
|
||||
groupUsage -= originInfo->LockedUsage();
|
||||
|
||||
originInfos.RemoveElementsBy(
|
||||
[&doomedOriginInfos](const auto& originInfo) {
|
||||
return doomedOriginInfos.Contains(originInfo) ||
|
||||
originInfo->LockedPersisted();
|
||||
});
|
||||
|
||||
originInfos.Sort(OriginInfoLRUComparator());
|
||||
|
||||
for (uint32_t i = 0; i < originInfos.Length(); i++) {
|
||||
if (mTemporaryStorageUsage - usage <= mTemporaryStorageLimit) {
|
||||
originInfos.TruncateLength(i);
|
||||
if (groupUsage <= quotaManager->GetGroupLimit()) {
|
||||
break;
|
||||
}
|
||||
|
||||
usage += originInfos[i]->LockedUsage();
|
||||
}
|
||||
|
||||
doomedOriginInfos.AppendElements(originInfos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return doomedOriginInfos;
|
||||
}();
|
||||
return originInfos;
|
||||
}
|
||||
|
||||
for (const auto& doomedOriginInfo : doomedOriginInfos) {
|
||||
#ifdef DEBUG
|
||||
{
|
||||
MutexAutoLock lock(mQuotaMutex);
|
||||
MOZ_ASSERT(!doomedOriginInfo->LockedPersisted());
|
||||
}
|
||||
#endif
|
||||
QuotaManager::OriginInfosFlatTraversable
|
||||
QuotaManager::LockedGetOriginInfosExceedingGlobalLimit(
|
||||
const OriginInfosFlatTraversable& aAlreadyDoomedOriginInfos,
|
||||
const uint64_t aAlreadyDoomedUsage) const {
|
||||
mQuotaMutex.AssertCurrentThreadOwns();
|
||||
|
||||
DeleteFilesForOrigin(doomedOriginInfo->mGroupInfo->mPersistenceType,
|
||||
doomedOriginInfo->mOrigin);
|
||||
OriginInfosFlatTraversable originInfos;
|
||||
for (const auto& entry : mGroupInfoPairs) {
|
||||
const auto& pair = entry.GetData();
|
||||
|
||||
MOZ_ASSERT(!entry.GetKey().IsEmpty());
|
||||
MOZ_ASSERT(pair);
|
||||
|
||||
RefPtr<GroupInfo> groupInfo =
|
||||
pair->LockedGetGroupInfo(PERSISTENCE_TYPE_TEMPORARY);
|
||||
if (groupInfo) {
|
||||
originInfos.AppendElements(groupInfo->mOriginInfos);
|
||||
}
|
||||
|
||||
nsTArray<OriginParams> doomedOrigins;
|
||||
groupInfo = pair->LockedGetGroupInfo(PERSISTENCE_TYPE_DEFAULT);
|
||||
if (groupInfo) {
|
||||
originInfos.AppendElements(groupInfo->mOriginInfos);
|
||||
}
|
||||
}
|
||||
|
||||
originInfos.RemoveElementsBy(
|
||||
[&aAlreadyDoomedOriginInfos](const auto& originInfo) {
|
||||
return aAlreadyDoomedOriginInfos.Contains(originInfo) ||
|
||||
originInfo->LockedPersisted();
|
||||
});
|
||||
|
||||
originInfos.Sort(OriginInfoLRUComparator());
|
||||
|
||||
uint64_t doomedUsage = 0;
|
||||
for (uint32_t i = 0; i < originInfos.Length(); i++) {
|
||||
if (mTemporaryStorageUsage - aAlreadyDoomedUsage - doomedUsage <=
|
||||
mTemporaryStorageLimit) {
|
||||
originInfos.TruncateLength(i);
|
||||
break;
|
||||
}
|
||||
|
||||
doomedUsage += originInfos[i]->LockedUsage();
|
||||
}
|
||||
|
||||
return originInfos;
|
||||
}
|
||||
|
||||
QuotaManager::OriginInfosFlatTraversable
|
||||
QuotaManager::GetOriginInfosExceedingLimits() const {
|
||||
MutexAutoLock lock(mQuotaMutex);
|
||||
|
||||
auto originInfos = LockedGetOriginInfosExceedingGroupLimit();
|
||||
|
||||
const uint64_t doomedUsage =
|
||||
std::accumulate(originInfos.cbegin(), originInfos.cend(), uint64_t(0),
|
||||
[](uint64_t oldValue, const auto& originInfo) {
|
||||
return oldValue + originInfo->LockedUsage();
|
||||
});
|
||||
|
||||
// Evicting origins that exceed their group limit also affects the global
|
||||
// temporary storage usage. If the global temporary storage limit would still
|
||||
// be exceeded after evicting the origins that were already selected, we need
|
||||
// to specifically evict origins to get below the global limit.
|
||||
if (mTemporaryStorageUsage - doomedUsage > mTemporaryStorageLimit) {
|
||||
originInfos.AppendElements(
|
||||
LockedGetOriginInfosExceedingGlobalLimit(originInfos, doomedUsage));
|
||||
}
|
||||
|
||||
return originInfos;
|
||||
}
|
||||
|
||||
void QuotaManager::ClearOrigins(
|
||||
const OriginInfosFlatTraversable& aDoomedOriginInfos) {
|
||||
AssertIsOnIOThread();
|
||||
|
||||
// XXX Does this need to be done a) in order and/or b) sequentially?
|
||||
// XXX We don't need to concatenate the results of the two steps. It would be
|
||||
// sufficient to chain the ranges for iteration.
|
||||
for (const auto& doomedOriginInfo : aDoomedOriginInfos) {
|
||||
#ifdef DEBUG
|
||||
{
|
||||
MutexAutoLock lock(mQuotaMutex);
|
||||
|
||||
for (const auto& doomedOriginInfo : doomedOriginInfos) {
|
||||
PersistenceType persistenceType =
|
||||
doomedOriginInfo->mGroupInfo->mPersistenceType;
|
||||
const GroupAndOrigin groupAndOrigin = {
|
||||
doomedOriginInfo->mGroupInfo->mGroup, doomedOriginInfo->mOrigin};
|
||||
LockedRemoveQuotaForOrigin(persistenceType, groupAndOrigin);
|
||||
|
||||
doomedOrigins.EmplaceBack(
|
||||
OriginParams(persistenceType, groupAndOrigin.mOrigin));
|
||||
}
|
||||
MOZ_ASSERT(!doomedOriginInfo->LockedPersisted());
|
||||
}
|
||||
#endif
|
||||
|
||||
return doomedOrigins;
|
||||
}();
|
||||
DeleteFilesForOrigin(doomedOriginInfo->mGroupInfo->mPersistenceType,
|
||||
doomedOriginInfo->mOrigin);
|
||||
}
|
||||
|
||||
for (const OriginParams& doomedOrigin : doomedOrigins) {
|
||||
OriginClearCompleted(doomedOrigin.mPersistenceType, doomedOrigin.mOrigin,
|
||||
struct OriginParams {
|
||||
nsCString mOrigin;
|
||||
PersistenceType mPersistenceType;
|
||||
};
|
||||
|
||||
nsTArray<OriginParams> clearedOrigins;
|
||||
|
||||
{
|
||||
MutexAutoLock lock(mQuotaMutex);
|
||||
|
||||
for (const auto& doomedOriginInfo : aDoomedOriginInfos) {
|
||||
// LockedRemoveQuotaForOrigin might remove the group info;
|
||||
// OriginInfo::mGroupInfo is only a raw pointer, so we need to store the
|
||||
// information for calling OriginClearCompleted below in a separate array.
|
||||
clearedOrigins.AppendElement(
|
||||
OriginParams{doomedOriginInfo->mOrigin,
|
||||
doomedOriginInfo->mGroupInfo->mPersistenceType});
|
||||
|
||||
LockedRemoveQuotaForOrigin(
|
||||
doomedOriginInfo->mGroupInfo->mPersistenceType,
|
||||
{doomedOriginInfo->mGroupInfo->mGroup, doomedOriginInfo->mOrigin});
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& clearedOrigin : clearedOrigins) {
|
||||
OriginClearCompleted(clearedOrigin.mPersistenceType, clearedOrigin.mOrigin,
|
||||
Nullable<Client::Type>());
|
||||
}
|
||||
}
|
||||
|
||||
void QuotaManager::CleanupTemporaryStorage() {
|
||||
AssertIsOnIOThread();
|
||||
|
||||
ClearOrigins(GetOriginInfosExceedingLimits());
|
||||
|
||||
if (mTemporaryStorageUsage > mTemporaryStorageLimit) {
|
||||
// If disk space is still low after origin clear, notify storage pressure.
|
||||
|
@ -114,14 +114,6 @@ class NS_NO_VTABLE OpenDirectoryListener : public RefCountedObject {
|
||||
virtual ~OpenDirectoryListener() = default;
|
||||
};
|
||||
|
||||
struct OriginParams {
|
||||
OriginParams(PersistenceType aPersistenceType, const nsACString& aOrigin)
|
||||
: mOrigin(aOrigin), mPersistenceType(aPersistenceType) {}
|
||||
|
||||
nsCString mOrigin;
|
||||
PersistenceType mPersistenceType;
|
||||
};
|
||||
|
||||
class QuotaManager final : public BackgroundThreadObject {
|
||||
friend class DirectoryLockImpl;
|
||||
friend class GroupInfo;
|
||||
@ -566,7 +558,20 @@ class QuotaManager final : public BackgroundThreadObject {
|
||||
int64_t aAccessTime, bool aPersisted,
|
||||
nsIFile* aDirectory);
|
||||
|
||||
void CheckTemporaryStorageLimits();
|
||||
using OriginInfosFlatTraversable =
|
||||
nsTArray<NotNull<RefPtr<const OriginInfo>>>;
|
||||
|
||||
OriginInfosFlatTraversable LockedGetOriginInfosExceedingGroupLimit() const;
|
||||
|
||||
OriginInfosFlatTraversable LockedGetOriginInfosExceedingGlobalLimit(
|
||||
const OriginInfosFlatTraversable& aAlreadyDoomedOriginInfos,
|
||||
uint64_t aAlreadyDoomedUsage) const;
|
||||
|
||||
OriginInfosFlatTraversable GetOriginInfosExceedingLimits() const;
|
||||
|
||||
void ClearOrigins(const OriginInfosFlatTraversable& aDoomedOriginInfos);
|
||||
|
||||
void CleanupTemporaryStorage();
|
||||
|
||||
void DeleteFilesForOrigin(PersistenceType aPersistenceType,
|
||||
const nsACString& aOrigin);
|
||||
@ -605,7 +610,7 @@ class QuotaManager final : public BackgroundThreadObject {
|
||||
// Accesses to mQuotaManagerShutdownSteps must be protected by mQuotaMutex.
|
||||
nsCString mQuotaManagerShutdownSteps;
|
||||
|
||||
mozilla::Mutex mQuotaMutex;
|
||||
mutable mozilla::Mutex mQuotaMutex;
|
||||
|
||||
nsClassHashtable<nsCStringHashKey, GroupInfoPair> mGroupInfoPairs;
|
||||
|
||||
|
@ -77,7 +77,10 @@ struct CopyablePtr {
|
||||
T mPtr;
|
||||
|
||||
template <typename U>
|
||||
explicit CopyablePtr(U aPtr) : mPtr{std::move(aPtr)} {}
|
||||
explicit CopyablePtr(U&& aPtr) : mPtr{std::forward<U>(aPtr)} {}
|
||||
|
||||
template <typename U>
|
||||
explicit CopyablePtr(CopyablePtr<U> aPtr) : mPtr{std::move(aPtr.mPtr)} {}
|
||||
};
|
||||
} // namespace detail
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user