Bug 1563023 - Part 3: Change client usage type to support the null value; r=asuth

This patch wraps the uint64_t type in a Maybe container, so the client usage can
represent a state when there are no files on disk for the given client. Zero
usage then represents a state when there are some files but they are empty or
the client tracks logical size (not physical size of files on disk) and the
logical size is zero. This can be useful especially for LocalStorage.

Differential Revision: https://phabricator.services.mozilla.com/D38181

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Jan Varga 2019-08-22 20:52:09 +00:00
Родитель cb20985c65
Коммит 0e46119bb9
7 изменённых файлов: 111 добавлений и 88 удалений

7
dom/cache/QuotaClient.cpp поставляемый
Просмотреть файл

@ -23,6 +23,7 @@ namespace {
using mozilla::Atomic;
using mozilla::MutexAutoLock;
using mozilla::Some;
using mozilla::Unused;
using mozilla::dom::ContentParentId;
using mozilla::dom::cache::DirPaddingFile;
@ -69,7 +70,7 @@ static nsresult GetBodyUsage(nsIFile* aDir, const Atomic<bool>& aCanceled,
}
MOZ_DIAGNOSTIC_ASSERT(fileSize >= 0);
aUsageInfo->AppendToFileUsage(fileSize);
aUsageInfo->AppendToFileUsage(Some(fileSize));
}
return NS_OK;
@ -414,7 +415,7 @@ class CacheQuotaClient final : public Client {
}
}
aUsageInfo->AppendToFileUsage(paddingSize);
aUsageInfo->AppendToFileUsage(Some(paddingSize));
nsCOMPtr<nsIDirectoryEnumerator> entries;
rv = dir->GetDirectoryEntries(getter_AddRefs(entries));
@ -478,7 +479,7 @@ class CacheQuotaClient final : public Client {
}
MOZ_DIAGNOSTIC_ASSERT(fileSize >= 0);
aUsageInfo->AppendToDatabaseUsage(fileSize);
aUsageInfo->AppendToDatabaseUsage(Some(fileSize));
continue;
}

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

@ -8910,10 +8910,10 @@ nsresult RemoveDatabaseFilesAndDirectory(nsIFile* aBaseDirectory,
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
}
uint64_t usage = 0;
uint64_t usage;
if (aQuotaManager) {
rv = FileManager::GetUsage(fmDirectory, &usage);
rv = FileManager::GetUsage(fmDirectory, usage);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
@ -8925,7 +8925,7 @@ nsresult RemoveDatabaseFilesAndDirectory(nsIFile* aBaseDirectory,
// information before returning the error.
if (aQuotaManager) {
uint64_t newUsage;
if (NS_SUCCEEDED(FileManager::GetUsage(fmDirectory, &newUsage))) {
if (NS_SUCCEEDED(FileManager::GetUsage(fmDirectory, newUsage))) {
MOZ_ASSERT(newUsage <= usage);
usage = usage - newUsage;
}
@ -15644,10 +15644,9 @@ nsresult FileManager::InitDirectory(nsIFile* aDirectory, nsIFile* aDatabaseFile,
}
// static
nsresult FileManager::GetUsage(nsIFile* aDirectory, uint64_t* aUsage) {
nsresult FileManager::GetUsage(nsIFile* aDirectory, Maybe<uint64_t>& aUsage) {
AssertIsOnIOThread();
MOZ_ASSERT(aDirectory);
MOZ_ASSERT(aUsage);
bool exists;
nsresult rv = aDirectory->Exists(&exists);
@ -15656,7 +15655,7 @@ nsresult FileManager::GetUsage(nsIFile* aDirectory, uint64_t* aUsage) {
}
if (!exists) {
*aUsage = 0;
aUsage.reset();
return NS_OK;
}
@ -15666,7 +15665,7 @@ nsresult FileManager::GetUsage(nsIFile* aDirectory, uint64_t* aUsage) {
return rv;
}
uint64_t usage = 0;
Maybe<uint64_t> usage;
nsCOMPtr<nsIFile> file;
while (NS_SUCCEEDED((rv = entries->GetNextFile(getter_AddRefs(file)))) &&
@ -15687,14 +15686,29 @@ nsresult FileManager::GetUsage(nsIFile* aDirectory, uint64_t* aUsage) {
return rv;
}
UsageInfo::IncrementUsage(&usage, uint64_t(fileSize));
UsageInfo::IncrementUsage(usage, Some(uint64_t(fileSize)));
}
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
*aUsage = usage;
aUsage = usage;
return NS_OK;
}
// static
nsresult FileManager::GetUsage(nsIFile* aDirectory, uint64_t& aUsage) {
AssertIsOnIOThread();
MOZ_ASSERT(aDirectory);
Maybe<uint64_t> usage;
nsresult rv = GetUsage(aDirectory, usage);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
aUsage = usage.valueOr(0);
return NS_OK;
}
@ -16100,20 +16114,20 @@ nsresult QuotaClient::InitOrigin(PersistenceType aPersistenceType,
MOZ_ASSERT(fileSize >= 0);
aUsageInfo->AppendToDatabaseUsage(uint64_t(fileSize));
aUsageInfo->AppendToDatabaseUsage(Some(uint64_t(fileSize)));
rv = walFile->GetFileSize(&fileSize);
if (NS_SUCCEEDED(rv)) {
MOZ_ASSERT(fileSize >= 0);
aUsageInfo->AppendToDatabaseUsage(uint64_t(fileSize));
aUsageInfo->AppendToDatabaseUsage(Some(uint64_t(fileSize)));
} else if (NS_WARN_IF(rv != NS_ERROR_FILE_NOT_FOUND &&
rv != NS_ERROR_FILE_TARGET_DOES_NOT_EXIST)) {
REPORT_TELEMETRY_INIT_ERR(kQuotaExternalError, IDB_GetWalFileSize);
return rv;
}
uint64_t usage;
rv = FileManager::GetUsage(fmDirectory, &usage);
Maybe<uint64_t> usage;
rv = FileManager::GetUsage(fmDirectory, usage);
if (NS_WARN_IF(NS_FAILED(rv))) {
REPORT_TELEMETRY_INIT_ERR(kQuotaExternalError, IDB_GetUsage);
return rv;
@ -16609,9 +16623,9 @@ nsresult QuotaClient::GetUsageForDirectoryInternal(nsIFile* aDirectory,
MOZ_ASSERT(fileSize >= 0);
if (aDatabaseFiles) {
aUsageInfo->AppendToDatabaseUsage(uint64_t(fileSize));
aUsageInfo->AppendToDatabaseUsage(Some(uint64_t(fileSize)));
} else {
aUsageInfo->AppendToFileUsage(uint64_t(fileSize));
aUsageInfo->AppendToFileUsage(Some(uint64_t(fileSize)));
}
}

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

@ -57,7 +57,9 @@ class FileManager final {
const nsACString& aOrigin,
uint32_t aTelemetryId);
static nsresult GetUsage(nsIFile* aDirectory, uint64_t* aUsage);
static nsresult GetUsage(nsIFile* aDirectory, Maybe<uint64_t>& aUsage);
static nsresult GetUsage(nsIFile* aDirectory, uint64_t& aUsage);
FileManager(PersistenceType aPersistenceType, const nsACString& aGroup,
const nsACString& aOrigin, const nsAString& aDatabaseName,

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

@ -8687,7 +8687,7 @@ nsresult QuotaClient::InitOrigin(PersistenceType aPersistenceType,
InitUsageForOrigin(aOrigin, usage);
}
aUsageInfo->AppendToDatabaseUsage(uint64_t(usage));
aUsageInfo->AppendToDatabaseUsage(Some(uint64_t(usage)));
} else if (usageFileExists) {
rv = usageFile->Remove(false);
if (NS_WARN_IF(NS_FAILED(rv))) {
@ -8777,7 +8777,7 @@ nsresult QuotaClient::GetUsageForOrigin(PersistenceType aPersistenceType,
int64_t usage;
if (mozilla::dom::GetUsageForOrigin(aOrigin, usage)) {
MOZ_ASSERT(usage >= 0);
aUsageInfo->AppendToDatabaseUsage(usage);
aUsageInfo->AppendToDatabaseUsage(Some(usage));
}
return NS_OK;

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

@ -604,13 +604,10 @@ namespace {
} // namespace
class ClientUsageArray final : public AutoTArray<uint64_t, Client::TYPE_MAX> {
class ClientUsageArray final
: public AutoTArray<Maybe<uint64_t>, Client::TYPE_MAX> {
public:
ClientUsageArray() {
for (uint32_t index = 0; index < uint32_t(Client::TypeMax()); index++) {
AppendElement(0);
}
}
ClientUsageArray() { SetLength(Client::TypeMax()); }
};
class OriginInfo final {
@ -635,8 +632,8 @@ class OriginInfo final {
#ifdef DEBUG
uint64_t usage = 0;
for (uint32_t index = 0; index < uint32_t(Client::TypeMax()); index++) {
AssertNoOverflow(usage, mClientUsages[index]);
usage += mClientUsages[index];
AssertNoOverflow(usage, mClientUsages[index].valueOr(0));
usage += mClientUsages[index].valueOr(0);
}
MOZ_ASSERT(mUsage == usage);
#endif
@ -1186,9 +1183,10 @@ class GetUsageOp final : public QuotaUsageRequestBase,
};
class GetOriginUsageOp final : public QuotaUsageRequestBase {
UsageInfo mUsageInfo;
nsCString mSuffix;
nsCString mGroup;
uint64_t mUsage;
uint64_t mFileUsage;
bool mFromMemory;
public:
@ -2858,8 +2856,10 @@ bool QuotaObject::LockedMaybeUpdateSize(int64_t aSize, bool aTruncate) {
AssertNoUnderflow(mOriginInfo->mUsage, delta);
mOriginInfo->mUsage -= delta;
AssertNoUnderflow(mOriginInfo->mClientUsages[mClientType], delta);
mOriginInfo->mClientUsages[mClientType] -= delta;
MOZ_ASSERT(mOriginInfo->mClientUsages[mClientType].isSome());
AssertNoUnderflow(mOriginInfo->mClientUsages[mClientType].value(), delta);
mOriginInfo->mClientUsages[mClientType] =
Some(mOriginInfo->mClientUsages[mClientType].value() - delta);
mSize = aSize;
}
@ -2874,8 +2874,9 @@ bool QuotaObject::LockedMaybeUpdateSize(int64_t aSize, bool aTruncate) {
uint64_t delta = aSize - mSize;
AssertNoOverflow(mOriginInfo->mClientUsages[mClientType], delta);
uint64_t newClientUsage = mOriginInfo->mClientUsages[mClientType] + delta;
AssertNoOverflow(mOriginInfo->mClientUsages[mClientType].valueOr(0), delta);
uint64_t newClientUsage =
mOriginInfo->mClientUsages[mClientType].valueOr(0) + delta;
AssertNoOverflow(mOriginInfo->mUsage, delta);
uint64_t newUsage = mOriginInfo->mUsage + delta;
@ -2971,8 +2972,8 @@ bool QuotaObject::LockedMaybeUpdateSize(int64_t aSize, bool aTruncate) {
AssertNoUnderflow(aSize, mSize);
delta = aSize - mSize;
AssertNoOverflow(mOriginInfo->mClientUsages[mClientType], delta);
newClientUsage = mOriginInfo->mClientUsages[mClientType] + delta;
AssertNoOverflow(mOriginInfo->mClientUsages[mClientType].valueOr(0), delta);
newClientUsage = mOriginInfo->mClientUsages[mClientType].valueOr(0) + delta;
AssertNoOverflow(mOriginInfo->mUsage, delta);
newUsage = mOriginInfo->mUsage + delta;
@ -3011,7 +3012,7 @@ bool QuotaObject::LockedMaybeUpdateSize(int64_t aSize, bool aTruncate) {
// Ok, we successfully freed enough space and the operation can continue
// without throwing the quota error.
mOriginInfo->mClientUsages[mClientType] = newClientUsage;
mOriginInfo->mClientUsages[mClientType] = Some(newClientUsage);
mOriginInfo->mUsage = newUsage;
if (!mOriginInfo->LockedPersisted()) {
@ -3034,7 +3035,7 @@ bool QuotaObject::LockedMaybeUpdateSize(int64_t aSize, bool aTruncate) {
return true;
}
mOriginInfo->mClientUsages[mClientType] = newClientUsage;
mOriginInfo->mClientUsages[mClientType] = Some(newClientUsage);
mOriginInfo->mUsage = newUsage;
if (!mOriginInfo->LockedPersisted()) {
@ -4388,12 +4389,12 @@ nsresult QuotaManager::InitializeOrigin(PersistenceType aPersistenceType,
}
if (trackQuota) {
uint64_t clientUsage = usageInfo.TotalUsage();
Maybe<uint64_t> clientUsage = usageInfo.TotalUsage();
clientUsages[clientType] = clientUsage;
AssertNoOverflow(usage, clientUsage);
usage += clientUsage;
AssertNoOverflow(usage, clientUsage.valueOr(0));
usage += clientUsage.valueOr(0);
}
}
if (NS_WARN_IF(NS_FAILED(rv))) {
@ -6749,8 +6750,8 @@ OriginInfo::OriginInfo(GroupInfo* aGroupInfo, const nsACString& aOrigin,
#ifdef DEBUG
uint64_t usage = 0;
for (uint32_t index = 0; index < uint32_t(Client::TypeMax()); index++) {
AssertNoOverflow(usage, aClientUsages[index]);
usage += aClientUsages[index];
AssertNoOverflow(usage, aClientUsages[index].valueOr(0));
usage += aClientUsages[index].valueOr(0);
}
MOZ_ASSERT(aUsage == usage);
#endif
@ -6761,8 +6762,9 @@ OriginInfo::OriginInfo(GroupInfo* aGroupInfo, const nsACString& aOrigin,
void OriginInfo::LockedDecreaseUsage(Client::Type aClientType, int64_t aSize) {
AssertCurrentThreadOwnsQuotaMutex();
AssertNoUnderflow(mClientUsages[aClientType], aSize);
mClientUsages[aClientType] -= aSize;
MOZ_ASSERT(mClientUsages[aClientType].isSome());
AssertNoUnderflow(mClientUsages[aClientType].value(), aSize);
mClientUsages[aClientType] = Some(mClientUsages[aClientType].value() - aSize);
AssertNoUnderflow(mUsage, aSize);
mUsage -= aSize;
@ -6782,9 +6784,9 @@ void OriginInfo::LockedDecreaseUsage(Client::Type aClientType, int64_t aSize) {
void OriginInfo::LockedResetUsageForClient(Client::Type aClientType) {
AssertCurrentThreadOwnsQuotaMutex();
uint64_t size = mClientUsages[aClientType];
uint64_t size = mClientUsages[aClientType].valueOr(0);
mClientUsages[aClientType] = 0;
mClientUsages[aClientType].reset();
AssertNoUnderflow(mUsage, size);
mUsage -= size;
@ -7697,7 +7699,6 @@ nsresult QuotaUsageRequestBase::GetUsageForOrigin(
AssertIsOnIOThread();
MOZ_ASSERT(aQuotaManager);
MOZ_ASSERT(aUsageInfo);
MOZ_ASSERT(aUsageInfo->TotalUsage() == 0);
nsCOMPtr<nsIFile> directory;
nsresult rv = aQuotaManager->GetDirectoryForOrigin(aPersistenceType, aOrigin,
@ -7982,7 +7983,7 @@ nsresult GetUsageOp::ProcessOrigin(QuotaManager* aQuotaManager,
}
ProcessOriginInternal(aQuotaManager, aPersistenceType, origin, timestamp,
persisted, usageInfo.TotalUsage());
persisted, usageInfo.TotalUsage().valueOr(0));
return NS_OK;
}
@ -8029,7 +8030,8 @@ void GetUsageOp::GetResponse(UsageRequestResponse& aResponse) {
}
}
GetOriginUsageOp::GetOriginUsageOp(const UsageRequestParams& aParams) {
GetOriginUsageOp::GetOriginUsageOp(const UsageRequestParams& aParams)
: mUsage(0), mFileUsage(0) {
AssertIsOnOwningThread();
MOZ_ASSERT(aParams.type() == UsageRequestParams::TOriginUsageParams);
@ -8051,7 +8053,8 @@ GetOriginUsageOp::GetOriginUsageOp(const UsageRequestParams& aParams) {
nsresult GetOriginUsageOp::DoDirectoryWork(QuotaManager* aQuotaManager) {
AssertIsOnIOThread();
MOZ_ASSERT(mUsageInfo.TotalUsage() == 0);
MOZ_ASSERT(mUsage == 0);
MOZ_ASSERT(mFileUsage == 0);
AUTO_PROFILER_LABEL("GetOriginUsageOp::DoDirectoryWork", OTHER);
@ -8072,29 +8075,27 @@ nsresult GetOriginUsageOp::DoDirectoryWork(QuotaManager* aQuotaManager) {
return rv;
}
// Get cached usage (the method doesn't have to stat any files).
uint64_t usage =
aQuotaManager->GetOriginUsage(mGroup, mOriginScope.GetOrigin());
// File usage is not tracked in memory separately, so just add to the
// database usage.
mUsageInfo.AppendToDatabaseUsage(usage);
// Get cached usage (the method doesn't have to stat any files). File usage
// is not tracked in memory separately, so just add to the total usage.
mUsage = aQuotaManager->GetOriginUsage(mGroup, mOriginScope.GetOrigin());
return NS_OK;
}
UsageInfo usageInfo;
// Add all the persistent/temporary/default storage files we care about.
for (const PersistenceType type : kAllPersistenceTypes) {
UsageInfo usageInfo;
rv = GetUsageForOrigin(aQuotaManager, type, mGroup,
mOriginScope.GetOrigin(), &usageInfo);
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;
}
mUsageInfo.Append(usageInfo);
}
mUsage = usageInfo.TotalUsage().valueOr(0);
mFileUsage = usageInfo.FileUsage().valueOr(0);
return NS_OK;
}
@ -8103,8 +8104,8 @@ void GetOriginUsageOp::GetResponse(UsageRequestResponse& aResponse) {
OriginUsageResponse usageResponse;
usageResponse.usage() = mUsageInfo.TotalUsage();
usageResponse.fileUsage() = mUsageInfo.FileUsage();
usageResponse.usage() = mUsage;
usageResponse.fileUsage() = mFileUsage;
aResponse = usageResponse;
}

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

@ -14,49 +14,54 @@
BEGIN_QUOTA_NAMESPACE
class UsageInfo {
class UsageInfo final {
public:
UsageInfo() : mDatabaseUsage(0), mFileUsage(0) {}
virtual ~UsageInfo() {}
void Append(const UsageInfo& aUsageInfo) {
IncrementUsage(&mDatabaseUsage, aUsageInfo.mDatabaseUsage);
IncrementUsage(&mFileUsage, aUsageInfo.mFileUsage);
IncrementUsage(mDatabaseUsage, aUsageInfo.mDatabaseUsage);
IncrementUsage(mFileUsage, aUsageInfo.mFileUsage);
}
void AppendToDatabaseUsage(uint64_t aUsage) {
IncrementUsage(&mDatabaseUsage, aUsage);
void AppendToDatabaseUsage(const Maybe<uint64_t>& aUsage) {
IncrementUsage(mDatabaseUsage, aUsage);
}
void AppendToFileUsage(uint64_t aUsage) {
IncrementUsage(&mFileUsage, aUsage);
void AppendToFileUsage(const Maybe<uint64_t>& aUsage) {
IncrementUsage(mFileUsage, aUsage);
}
uint64_t DatabaseUsage() { return mDatabaseUsage; }
const Maybe<uint64_t>& DatabaseUsage() const { return mDatabaseUsage; }
uint64_t FileUsage() { return mFileUsage; }
const Maybe<uint64_t>& FileUsage() const { return mFileUsage; }
Maybe<uint64_t> TotalUsage() {
Maybe<uint64_t> totalUsage;
IncrementUsage(totalUsage, mDatabaseUsage);
IncrementUsage(totalUsage, mFileUsage);
uint64_t TotalUsage() {
uint64_t totalUsage = mDatabaseUsage;
IncrementUsage(&totalUsage, mFileUsage);
return totalUsage;
}
static void IncrementUsage(uint64_t* aUsage, uint64_t aDelta) {
MOZ_ASSERT(aUsage);
CheckedUint64 value = *aUsage;
value += aDelta;
static void IncrementUsage(Maybe<uint64_t>& aUsage,
const Maybe<uint64_t>& aDelta) {
if (aDelta.isNothing()) {
return;
}
CheckedUint64 value = aUsage.valueOr(0);
value += aDelta.value();
if (value.isValid()) {
*aUsage = value.value();
aUsage = Some(value.value());
} else {
*aUsage = UINT64_MAX;
aUsage = Some(UINT64_MAX);
}
}
private:
uint64_t mDatabaseUsage;
uint64_t mFileUsage;
Maybe<uint64_t> mDatabaseUsage;
Maybe<uint64_t> mFileUsage;
};
END_QUOTA_NAMESPACE

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

@ -1676,7 +1676,7 @@ nsresult QuotaClient::GetUsageForOrigin(PersistenceType aPersistenceType,
MOZ_ASSERT(fileSize >= 0);
aUsageInfo->AppendToDatabaseUsage(uint64_t(fileSize));
aUsageInfo->AppendToDatabaseUsage(Some(uint64_t(fileSize)));
}
if (NS_WARN_IF(NS_FAILED(rv))) {
return rv;