зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1576593 - P2 - Change the way for tunneling quota information to SQLite; r=janv
Differential Revision: https://phabricator.services.mozilla.com/D48183 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
20f43c02f7
Коммит
a973874d9b
|
@ -233,11 +233,15 @@ void Context::QuotaInitRunnable::OpenDirectory() {
|
||||||
|
|
||||||
void Context::QuotaInitRunnable::DirectoryLockAcquired(DirectoryLock* aLock) {
|
void Context::QuotaInitRunnable::DirectoryLockAcquired(DirectoryLock* aLock) {
|
||||||
NS_ASSERT_OWNINGTHREAD(QuotaInitRunnable);
|
NS_ASSERT_OWNINGTHREAD(QuotaInitRunnable);
|
||||||
|
MOZ_DIAGNOSTIC_ASSERT(aLock);
|
||||||
MOZ_DIAGNOSTIC_ASSERT(mState == STATE_WAIT_FOR_DIRECTORY_LOCK);
|
MOZ_DIAGNOSTIC_ASSERT(mState == STATE_WAIT_FOR_DIRECTORY_LOCK);
|
||||||
MOZ_DIAGNOSTIC_ASSERT(!mDirectoryLock);
|
MOZ_DIAGNOSTIC_ASSERT(!mDirectoryLock);
|
||||||
|
|
||||||
mDirectoryLock = aLock;
|
mDirectoryLock = aLock;
|
||||||
|
|
||||||
|
MOZ_DIAGNOSTIC_ASSERT(mDirectoryLock->GetId() >= 0);
|
||||||
|
mQuotaInfo.mDirectoryLockId = mDirectoryLock->GetId();
|
||||||
|
|
||||||
if (mCanceled) {
|
if (mCanceled) {
|
||||||
Complete(NS_ERROR_ABORT);
|
Complete(NS_ERROR_ABORT);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -27,6 +27,7 @@ namespace cache {
|
||||||
|
|
||||||
using mozilla::dom::quota::AssertIsOnIOThread;
|
using mozilla::dom::quota::AssertIsOnIOThread;
|
||||||
using mozilla::dom::quota::Client;
|
using mozilla::dom::quota::Client;
|
||||||
|
using mozilla::dom::quota::IntCString;
|
||||||
using mozilla::dom::quota::PERSISTENCE_TYPE_DEFAULT;
|
using mozilla::dom::quota::PERSISTENCE_TYPE_DEFAULT;
|
||||||
using mozilla::dom::quota::PersistenceType;
|
using mozilla::dom::quota::PersistenceType;
|
||||||
|
|
||||||
|
@ -123,6 +124,7 @@ void DBAction::RunOnTarget(Resolver* aResolver, const QuotaInfo& aQuotaInfo,
|
||||||
nsresult DBAction::OpenConnection(const QuotaInfo& aQuotaInfo, nsIFile* aDBDir,
|
nsresult DBAction::OpenConnection(const QuotaInfo& aQuotaInfo, nsIFile* aDBDir,
|
||||||
mozIStorageConnection** aConnOut) {
|
mozIStorageConnection** aConnOut) {
|
||||||
MOZ_ASSERT(!NS_IsMainThread());
|
MOZ_ASSERT(!NS_IsMainThread());
|
||||||
|
MOZ_DIAGNOSTIC_ASSERT(aQuotaInfo.mDirectoryLockId >= 0);
|
||||||
MOZ_DIAGNOSTIC_ASSERT(aDBDir);
|
MOZ_DIAGNOSTIC_ASSERT(aDBDir);
|
||||||
MOZ_DIAGNOSTIC_ASSERT(aConnOut);
|
MOZ_DIAGNOSTIC_ASSERT(aConnOut);
|
||||||
|
|
||||||
|
@ -168,6 +170,7 @@ void SyncDBAction::RunWithDBOnTarget(Resolver* aResolver,
|
||||||
nsresult OpenDBConnection(const QuotaInfo& aQuotaInfo, nsIFile* aDBDir,
|
nsresult OpenDBConnection(const QuotaInfo& aQuotaInfo, nsIFile* aDBDir,
|
||||||
mozIStorageConnection** aConnOut) {
|
mozIStorageConnection** aConnOut) {
|
||||||
MOZ_ASSERT(!NS_IsMainThread());
|
MOZ_ASSERT(!NS_IsMainThread());
|
||||||
|
MOZ_DIAGNOSTIC_ASSERT(aQuotaInfo.mDirectoryLockId >= -1);
|
||||||
MOZ_DIAGNOSTIC_ASSERT(aDBDir);
|
MOZ_DIAGNOSTIC_ASSERT(aDBDir);
|
||||||
MOZ_DIAGNOSTIC_ASSERT(aConnOut);
|
MOZ_DIAGNOSTIC_ASSERT(aConnOut);
|
||||||
|
|
||||||
|
@ -208,19 +211,16 @@ nsresult OpenDBConnection(const QuotaInfo& aQuotaInfo, nsIFile* aDBDir,
|
||||||
|
|
||||||
nsCOMPtr<nsIFileURL> dbFileUrl;
|
nsCOMPtr<nsIFileURL> dbFileUrl;
|
||||||
|
|
||||||
nsAutoCString type;
|
const nsCString directoryLockIdClause =
|
||||||
PersistenceTypeToText(PERSISTENCE_TYPE_DEFAULT, type);
|
aQuotaInfo.mDirectoryLockId >= 0
|
||||||
|
? NS_LITERAL_CSTRING("&directoryLockId=") +
|
||||||
|
IntCString(aQuotaInfo.mDirectoryLockId)
|
||||||
|
: EmptyCString();
|
||||||
|
|
||||||
nsAutoCString clientType;
|
rv =
|
||||||
Client::TypeToText(Client::DOMCACHE, clientType);
|
NS_MutateURI(mutator)
|
||||||
|
.SetQuery(NS_LITERAL_CSTRING("cache=private") + directoryLockIdClause)
|
||||||
rv = NS_MutateURI(mutator)
|
.Finalize(dbFileUrl);
|
||||||
.SetQuery(NS_LITERAL_CSTRING("persistenceType=") + type +
|
|
||||||
NS_LITERAL_CSTRING("&group=") + aQuotaInfo.mGroup +
|
|
||||||
NS_LITERAL_CSTRING("&origin=") + aQuotaInfo.mOrigin +
|
|
||||||
NS_LITERAL_CSTRING("&clientType=") + clientType +
|
|
||||||
NS_LITERAL_CSTRING("&cache=private"))
|
|
||||||
.Finalize(dbFileUrl);
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
|
@ -40,8 +40,8 @@ class DBAction : public Action {
|
||||||
mozIStorageConnection* aConn) = 0;
|
mozIStorageConnection* aConn) = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual void RunOnTarget(Resolver* aResolver, const QuotaInfo& aQuotaInfo,
|
void RunOnTarget(Resolver* aResolver, const QuotaInfo& aQuotaInfo,
|
||||||
Data* aOptionalData) override;
|
Data* aOptionalData) override;
|
||||||
|
|
||||||
nsresult OpenConnection(const QuotaInfo& aQuotaInfo, nsIFile* aQuotaDir,
|
nsresult OpenConnection(const QuotaInfo& aQuotaInfo, nsIFile* aQuotaDir,
|
||||||
mozIStorageConnection** aConnOut);
|
mozIStorageConnection** aConnOut);
|
||||||
|
|
|
@ -148,8 +148,8 @@ class DeleteOrphanedBodyAction final : public Action {
|
||||||
mDeletedBodyIdList.AppendElement(aBodyId);
|
mDeletedBodyIdList.AppendElement(aBodyId);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void RunOnTarget(Resolver* aResolver, const QuotaInfo& aQuotaInfo,
|
void RunOnTarget(Resolver* aResolver, const QuotaInfo& aQuotaInfo,
|
||||||
Data*) override {
|
Data*) override {
|
||||||
MOZ_DIAGNOSTIC_ASSERT(aResolver);
|
MOZ_DIAGNOSTIC_ASSERT(aResolver);
|
||||||
MOZ_DIAGNOSTIC_ASSERT(aQuotaInfo.mDir);
|
MOZ_DIAGNOSTIC_ASSERT(aQuotaInfo.mDir);
|
||||||
|
|
||||||
|
|
|
@ -115,6 +115,11 @@ static nsresult LockedGetPaddingSizeFromDB(nsIFile* aDir,
|
||||||
QuotaInfo quotaInfo;
|
QuotaInfo quotaInfo;
|
||||||
quotaInfo.mGroup = aGroup;
|
quotaInfo.mGroup = aGroup;
|
||||||
quotaInfo.mOrigin = aOrigin;
|
quotaInfo.mOrigin = aOrigin;
|
||||||
|
// This should only be called during the temporary storage is initializing.
|
||||||
|
// And at that moment, we haven't constructed in-memory objects
|
||||||
|
// (e.g. QuotaObject) yet. So, passing a specific id to not get a QuotaObject
|
||||||
|
// on the TelemetryVFS.
|
||||||
|
MOZ_DIAGNOSTIC_ASSERT(quotaInfo.mDirectoryLockId == -1);
|
||||||
nsresult rv = mozilla::dom::cache::OpenDBConnection(quotaInfo, aDir,
|
nsresult rv = mozilla::dom::cache::OpenDBConnection(quotaInfo, aDir,
|
||||||
getter_AddRefs(conn));
|
getter_AddRefs(conn));
|
||||||
if (rv == NS_ERROR_FILE_NOT_FOUND ||
|
if (rv == NS_ERROR_FILE_NOT_FOUND ||
|
||||||
|
@ -432,11 +437,24 @@ class CacheQuotaClient final : public Client {
|
||||||
dir, DirPaddingFile::TMP_FILE) ||
|
dir, DirPaddingFile::TMP_FILE) ||
|
||||||
NS_WARN_IF(NS_FAILED(mozilla::dom::cache::LockedDirectoryPaddingGet(
|
NS_WARN_IF(NS_FAILED(mozilla::dom::cache::LockedDirectoryPaddingGet(
|
||||||
dir, &paddingSize)))) {
|
dir, &paddingSize)))) {
|
||||||
rv = LockedGetPaddingSizeFromDB(dir, aGroup, aOrigin, &paddingSize);
|
if (aInitializing) {
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
rv = LockedGetPaddingSizeFromDB(dir, aGroup, aOrigin, &paddingSize);
|
||||||
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
|
REPORT_TELEMETRY_ERR_IN_INIT(aInitializing, kQuotaInternalError,
|
||||||
|
Cache_GetPaddingSize);
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// XXXtt This should be handled in a better way.
|
||||||
|
// If there is no another action/operation for Cache on other threads,
|
||||||
|
// it means the previous action failed. And we should be safe to get
|
||||||
|
// the padding size from the database.
|
||||||
|
// However, if there is other actions access the files on Cache IO
|
||||||
|
// thread, then we shouldn't touch the file here.
|
||||||
REPORT_TELEMETRY_ERR_IN_INIT(aInitializing, kQuotaInternalError,
|
REPORT_TELEMETRY_ERR_IN_INIT(aInitializing, kQuotaInternalError,
|
||||||
Cache_GetPaddingSize);
|
Cache_GetPaddingSize);
|
||||||
return rv;
|
|
||||||
|
return NS_ERROR_ABORT;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,6 +33,9 @@ struct QuotaInfo {
|
||||||
nsCString mSuffix;
|
nsCString mSuffix;
|
||||||
nsCString mGroup;
|
nsCString mGroup;
|
||||||
nsCString mOrigin;
|
nsCString mOrigin;
|
||||||
|
int64_t mDirectoryLockId;
|
||||||
|
|
||||||
|
QuotaInfo() : mDirectoryLockId(-1) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef std::function<void(nsCOMPtr<nsIInputStream>&&)> InputStreamResolver;
|
typedef std::function<void(nsCOMPtr<nsIInputStream>&&)> InputStreamResolver;
|
||||||
|
|
|
@ -3898,9 +3898,7 @@ nsresult UpgradeSchemaFrom25_0To26_0(mozIStorageConnection* aConnection) {
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult GetDatabaseFileURL(nsIFile* aDatabaseFile,
|
nsresult GetDatabaseFileURL(nsIFile* aDatabaseFile, int64_t aDirectoryLockId,
|
||||||
PersistenceType aPersistenceType,
|
|
||||||
const nsACString& aGroup, const nsACString& aOrigin,
|
|
||||||
uint32_t aTelemetryId, nsIFileURL** aResult) {
|
uint32_t aTelemetryId, nsIFileURL** aResult) {
|
||||||
MOZ_ASSERT(aDatabaseFile);
|
MOZ_ASSERT(aDatabaseFile);
|
||||||
MOZ_ASSERT(aResult);
|
MOZ_ASSERT(aResult);
|
||||||
|
@ -3927,11 +3925,14 @@ nsresult GetDatabaseFileURL(nsIFile* aDatabaseFile,
|
||||||
|
|
||||||
nsCOMPtr<nsIFileURL> fileUrl;
|
nsCOMPtr<nsIFileURL> fileUrl;
|
||||||
|
|
||||||
nsAutoCString type;
|
// The aDirectoryLock should only be a nullptr when the temporary storage
|
||||||
PersistenceTypeToText(aPersistenceType, type);
|
// hasn't been initialized. At that time, we don't have in-memory objects
|
||||||
|
// (e.g. originInfo) so that it doesn't make sense to tunnel the
|
||||||
nsAutoCString clientType;
|
// directoryLockId to TelemetryVFS to get the quotaObject.
|
||||||
Client::TypeToText(Client::IDB, clientType);
|
const nsCString directoryLockIdClause =
|
||||||
|
aDirectoryLockId >= 0 ? NS_LITERAL_CSTRING("&directoryLockId=") +
|
||||||
|
IntCString(aDirectoryLockId)
|
||||||
|
: EmptyCString();
|
||||||
|
|
||||||
nsAutoCString telemetryFilenameClause;
|
nsAutoCString telemetryFilenameClause;
|
||||||
if (aTelemetryId) {
|
if (aTelemetryId) {
|
||||||
|
@ -3941,12 +3942,8 @@ nsresult GetDatabaseFileURL(nsIFile* aDatabaseFile,
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = NS_MutateURI(mutator)
|
rv = NS_MutateURI(mutator)
|
||||||
.SetQuery(NS_LITERAL_CSTRING("persistenceType=") + type +
|
.SetQuery(NS_LITERAL_CSTRING("cache=private") +
|
||||||
NS_LITERAL_CSTRING("&group=") + aGroup +
|
directoryLockIdClause + telemetryFilenameClause)
|
||||||
NS_LITERAL_CSTRING("&origin=") + aOrigin +
|
|
||||||
NS_LITERAL_CSTRING("&clientType=") + clientType +
|
|
||||||
NS_LITERAL_CSTRING("&cache=private") +
|
|
||||||
telemetryFilenameClause)
|
|
||||||
.Finalize(fileUrl);
|
.Finalize(fileUrl);
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
return rv;
|
return rv;
|
||||||
|
@ -4167,14 +4164,14 @@ nsresult OpenDatabaseAndHandleBusy(mozIStorageService* aStorageService,
|
||||||
|
|
||||||
nsresult CreateStorageConnection(nsIFile* aDBFile, nsIFile* aFMDirectory,
|
nsresult CreateStorageConnection(nsIFile* aDBFile, nsIFile* aFMDirectory,
|
||||||
const nsAString& aName,
|
const nsAString& aName,
|
||||||
PersistenceType aPersistenceType,
|
|
||||||
const nsACString& aGroup,
|
|
||||||
const nsACString& aOrigin,
|
const nsACString& aOrigin,
|
||||||
|
int64_t aDirectoryLockId,
|
||||||
uint32_t aTelemetryId,
|
uint32_t aTelemetryId,
|
||||||
mozIStorageConnection** aConnection) {
|
mozIStorageConnection** aConnection) {
|
||||||
AssertIsOnIOThread();
|
AssertIsOnIOThread();
|
||||||
MOZ_ASSERT(aDBFile);
|
MOZ_ASSERT(aDBFile);
|
||||||
MOZ_ASSERT(aFMDirectory);
|
MOZ_ASSERT(aFMDirectory);
|
||||||
|
MOZ_ASSERT(aDirectoryLockId >= -1);
|
||||||
MOZ_ASSERT(aConnection);
|
MOZ_ASSERT(aConnection);
|
||||||
|
|
||||||
AUTO_PROFILER_LABEL("CreateStorageConnection", DOM);
|
AUTO_PROFILER_LABEL("CreateStorageConnection", DOM);
|
||||||
|
@ -4183,8 +4180,8 @@ nsresult CreateStorageConnection(nsIFile* aDBFile, nsIFile* aFMDirectory,
|
||||||
bool exists;
|
bool exists;
|
||||||
|
|
||||||
nsCOMPtr<nsIFileURL> dbFileUrl;
|
nsCOMPtr<nsIFileURL> dbFileUrl;
|
||||||
rv = GetDatabaseFileURL(aDBFile, aPersistenceType, aGroup, aOrigin,
|
rv = GetDatabaseFileURL(aDBFile, aDirectoryLockId, aTelemetryId,
|
||||||
aTelemetryId, getter_AddRefs(dbFileUrl));
|
getter_AddRefs(dbFileUrl));
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
@ -4629,14 +4626,13 @@ already_AddRefed<nsIFile> GetFileForPath(const nsAString& aPath) {
|
||||||
return file.forget();
|
return file.forget();
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult GetStorageConnection(nsIFile* aDatabaseFile,
|
nsresult GetStorageConnection(nsIFile* aDatabaseFile, int64_t aDirectoryLockId,
|
||||||
PersistenceType aPersistenceType,
|
uint32_t aTelemetryId,
|
||||||
const nsACString& aGroup,
|
|
||||||
const nsACString& aOrigin, uint32_t aTelemetryId,
|
|
||||||
mozIStorageConnection** aConnection) {
|
mozIStorageConnection** aConnection) {
|
||||||
MOZ_ASSERT(!NS_IsMainThread());
|
MOZ_ASSERT(!NS_IsMainThread());
|
||||||
MOZ_ASSERT(!IsOnBackgroundThread());
|
MOZ_ASSERT(!IsOnBackgroundThread());
|
||||||
MOZ_ASSERT(aDatabaseFile);
|
MOZ_ASSERT(aDatabaseFile);
|
||||||
|
MOZ_ASSERT(aDirectoryLockId >= 0);
|
||||||
MOZ_ASSERT(aConnection);
|
MOZ_ASSERT(aConnection);
|
||||||
|
|
||||||
AUTO_PROFILER_LABEL("GetStorageConnection", DOM);
|
AUTO_PROFILER_LABEL("GetStorageConnection", DOM);
|
||||||
|
@ -4653,8 +4649,8 @@ nsresult GetStorageConnection(nsIFile* aDatabaseFile,
|
||||||
}
|
}
|
||||||
|
|
||||||
nsCOMPtr<nsIFileURL> dbFileUrl;
|
nsCOMPtr<nsIFileURL> dbFileUrl;
|
||||||
rv = GetDatabaseFileURL(aDatabaseFile, aPersistenceType, aGroup, aOrigin,
|
rv = GetDatabaseFileURL(aDatabaseFile, aDirectoryLockId, aTelemetryId,
|
||||||
aTelemetryId, getter_AddRefs(dbFileUrl));
|
getter_AddRefs(dbFileUrl));
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
@ -4686,14 +4682,13 @@ nsresult GetStorageConnection(nsIFile* aDatabaseFile,
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult GetStorageConnection(const nsAString& aDatabaseFilePath,
|
nsresult GetStorageConnection(const nsAString& aDatabaseFilePath,
|
||||||
PersistenceType aPersistenceType,
|
int64_t aDirectoryLockId, uint32_t aTelemetryId,
|
||||||
const nsACString& aGroup,
|
|
||||||
const nsACString& aOrigin, uint32_t aTelemetryId,
|
|
||||||
mozIStorageConnection** aConnection) {
|
mozIStorageConnection** aConnection) {
|
||||||
MOZ_ASSERT(!NS_IsMainThread());
|
MOZ_ASSERT(!NS_IsMainThread());
|
||||||
MOZ_ASSERT(!IsOnBackgroundThread());
|
MOZ_ASSERT(!IsOnBackgroundThread());
|
||||||
MOZ_ASSERT(!aDatabaseFilePath.IsEmpty());
|
MOZ_ASSERT(!aDatabaseFilePath.IsEmpty());
|
||||||
MOZ_ASSERT(StringEndsWith(aDatabaseFilePath, kSQLiteSuffix));
|
MOZ_ASSERT(StringEndsWith(aDatabaseFilePath, kSQLiteSuffix));
|
||||||
|
MOZ_ASSERT(aDirectoryLockId >= 0);
|
||||||
MOZ_ASSERT(aConnection);
|
MOZ_ASSERT(aConnection);
|
||||||
|
|
||||||
nsCOMPtr<nsIFile> dbFile = GetFileForPath(aDatabaseFilePath);
|
nsCOMPtr<nsIFile> dbFile = GetFileForPath(aDatabaseFilePath);
|
||||||
|
@ -4702,8 +4697,8 @@ nsresult GetStorageConnection(const nsAString& aDatabaseFilePath,
|
||||||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
return GetStorageConnection(dbFile, aPersistenceType, aGroup, aOrigin,
|
return GetStorageConnection(dbFile, aDirectoryLockId, aTelemetryId,
|
||||||
aTelemetryId, aConnection);
|
aConnection);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
|
@ -5796,6 +5791,7 @@ class Database final
|
||||||
const nsCString mId;
|
const nsCString mId;
|
||||||
const nsString mFilePath;
|
const nsString mFilePath;
|
||||||
uint32_t mActiveMutableFileCount;
|
uint32_t mActiveMutableFileCount;
|
||||||
|
int64_t mDirectoryLockId;
|
||||||
const uint32_t mTelemetryId;
|
const uint32_t mTelemetryId;
|
||||||
const PersistenceType mPersistenceType;
|
const PersistenceType mPersistenceType;
|
||||||
const bool mFileHandleDisabled;
|
const bool mFileHandleDisabled;
|
||||||
|
@ -5846,6 +5842,8 @@ class Database final
|
||||||
|
|
||||||
const nsCString& Id() const { return mId; }
|
const nsCString& Id() const { return mId; }
|
||||||
|
|
||||||
|
int64_t DirectoryLockId() const { return mDirectoryLockId; }
|
||||||
|
|
||||||
uint32_t TelemetryId() const { return mTelemetryId; }
|
uint32_t TelemetryId() const { return mTelemetryId; }
|
||||||
|
|
||||||
PersistenceType Type() const { return mPersistenceType; }
|
PersistenceType Type() const { return mPersistenceType; }
|
||||||
|
@ -6672,6 +6670,7 @@ class FactoryOp
|
||||||
nsCString mOrigin;
|
nsCString mOrigin;
|
||||||
nsCString mDatabaseId;
|
nsCString mDatabaseId;
|
||||||
nsString mDatabaseFilePath;
|
nsString mDatabaseFilePath;
|
||||||
|
int64_t mDirectoryLockId;
|
||||||
State mState;
|
State mState;
|
||||||
bool mWaitingForPermissionRetry;
|
bool mWaitingForPermissionRetry;
|
||||||
bool mEnforcingQuota;
|
bool mEnforcingQuota;
|
||||||
|
@ -8333,6 +8332,7 @@ class DatabaseMaintenance final : public Runnable {
|
||||||
const nsCString mGroup;
|
const nsCString mGroup;
|
||||||
const nsCString mOrigin;
|
const nsCString mOrigin;
|
||||||
const nsString mDatabasePath;
|
const nsString mDatabasePath;
|
||||||
|
int64_t mDirectoryLockId;
|
||||||
nsCOMPtr<nsIRunnable> mCompleteCallback;
|
nsCOMPtr<nsIRunnable> mCompleteCallback;
|
||||||
const PersistenceType mPersistenceType;
|
const PersistenceType mPersistenceType;
|
||||||
|
|
||||||
|
@ -8346,7 +8346,12 @@ class DatabaseMaintenance final : public Runnable {
|
||||||
mGroup(aGroup),
|
mGroup(aGroup),
|
||||||
mOrigin(aOrigin),
|
mOrigin(aOrigin),
|
||||||
mDatabasePath(aDatabasePath),
|
mDatabasePath(aDatabasePath),
|
||||||
mPersistenceType(aPersistenceType) {}
|
mPersistenceType(aPersistenceType) {
|
||||||
|
MOZ_ASSERT(aDirectoryLock);
|
||||||
|
|
||||||
|
MOZ_ASSERT(mDirectoryLock->GetId() >= 0);
|
||||||
|
mDirectoryLockId = mDirectoryLock->GetId();
|
||||||
|
}
|
||||||
|
|
||||||
const nsString& DatabasePath() const { return mDatabasePath; }
|
const nsString& DatabasePath() const { return mDatabasePath; }
|
||||||
|
|
||||||
|
@ -10910,10 +10915,9 @@ nsresult ConnectionPool::GetOrCreateConnection(
|
||||||
MOZ_ASSERT(!dbInfo->mDEBUGConnectionThread);
|
MOZ_ASSERT(!dbInfo->mDEBUGConnectionThread);
|
||||||
|
|
||||||
nsCOMPtr<mozIStorageConnection> storageConnection;
|
nsCOMPtr<mozIStorageConnection> storageConnection;
|
||||||
nsresult rv = GetStorageConnection(aDatabase->FilePath(), aDatabase->Type(),
|
nsresult rv = GetStorageConnection(
|
||||||
aDatabase->Group(), aDatabase->Origin(),
|
aDatabase->FilePath(), aDatabase->DirectoryLockId(),
|
||||||
aDatabase->TelemetryId(),
|
aDatabase->TelemetryId(), getter_AddRefs(storageConnection));
|
||||||
getter_AddRefs(storageConnection));
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
@ -12598,6 +12602,10 @@ Database::Database(Factory* aFactory, const PrincipalInfo& aPrincipalInfo,
|
||||||
MOZ_ASSERT(aFileManager);
|
MOZ_ASSERT(aFileManager);
|
||||||
MOZ_ASSERT_IF(aChromeWriteAccessAllowed,
|
MOZ_ASSERT_IF(aChromeWriteAccessAllowed,
|
||||||
aPrincipalInfo.type() == PrincipalInfo::TSystemPrincipalInfo);
|
aPrincipalInfo.type() == PrincipalInfo::TSystemPrincipalInfo);
|
||||||
|
|
||||||
|
MOZ_ASSERT(mDirectoryLock);
|
||||||
|
MOZ_ASSERT(mDirectoryLock->GetId() >= 0);
|
||||||
|
mDirectoryLockId = mDirectoryLock->GetId();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Database::Invalidate() {
|
void Database::Invalidate() {
|
||||||
|
@ -15614,8 +15622,6 @@ already_AddRefed<nsIFile> FileManager::GetCheckedFileForId(nsIFile* aDirectory,
|
||||||
|
|
||||||
// static
|
// static
|
||||||
nsresult FileManager::InitDirectory(nsIFile* aDirectory, nsIFile* aDatabaseFile,
|
nsresult FileManager::InitDirectory(nsIFile* aDirectory, nsIFile* aDatabaseFile,
|
||||||
PersistenceType aPersistenceType,
|
|
||||||
const nsACString& aGroup,
|
|
||||||
const nsACString& aOrigin,
|
const nsACString& aOrigin,
|
||||||
uint32_t aTelemetryId) {
|
uint32_t aTelemetryId) {
|
||||||
AssertIsOnIOThread();
|
AssertIsOnIOThread();
|
||||||
|
@ -15683,7 +15689,7 @@ nsresult FileManager::InitDirectory(nsIFile* aDirectory, nsIFile* aDatabaseFile,
|
||||||
if (hasElements) {
|
if (hasElements) {
|
||||||
nsCOMPtr<mozIStorageConnection> connection;
|
nsCOMPtr<mozIStorageConnection> connection;
|
||||||
rv = CreateStorageConnection(aDatabaseFile, aDirectory, VoidString(),
|
rv = CreateStorageConnection(aDatabaseFile, aDirectory, VoidString(),
|
||||||
aPersistenceType, aGroup, aOrigin,
|
aOrigin, /* aDirectoryLockId */ -1,
|
||||||
aTelemetryId, getter_AddRefs(connection));
|
aTelemetryId, getter_AddRefs(connection));
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
return rv;
|
return rv;
|
||||||
|
@ -16224,8 +16230,7 @@ nsresult QuotaClient::InitOrigin(PersistenceType aPersistenceType,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rv = FileManager::InitDirectory(fmDirectory, databaseFile, aPersistenceType,
|
rv = FileManager::InitDirectory(fmDirectory, databaseFile, aOrigin,
|
||||||
aGroup, aOrigin,
|
|
||||||
TelemetryIdForFile(databaseFile));
|
TelemetryIdForFile(databaseFile));
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
REPORT_TELEMETRY_INIT_ERR(kQuotaInternalError, IDB_InitDirectory);
|
REPORT_TELEMETRY_INIT_ERR(kQuotaInternalError, IDB_InitDirectory);
|
||||||
|
@ -17612,8 +17617,8 @@ void DatabaseMaintenance::PerformMaintenanceOnDatabase() {
|
||||||
MOZ_ASSERT(databaseFile);
|
MOZ_ASSERT(databaseFile);
|
||||||
|
|
||||||
nsCOMPtr<mozIStorageConnection> connection;
|
nsCOMPtr<mozIStorageConnection> connection;
|
||||||
nsresult rv = GetStorageConnection(databaseFile, mPersistenceType, mGroup,
|
nsresult rv = GetStorageConnection(databaseFile, mDirectoryLockId,
|
||||||
mOrigin, TelemetryIdForFile(databaseFile),
|
TelemetryIdForFile(databaseFile),
|
||||||
getter_AddRefs(connection));
|
getter_AddRefs(connection));
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
return;
|
return;
|
||||||
|
@ -19294,6 +19299,7 @@ FactoryOp::FactoryOp(Factory* aFactory,
|
||||||
mFactory(aFactory),
|
mFactory(aFactory),
|
||||||
mContentParent(std::move(aContentParent)),
|
mContentParent(std::move(aContentParent)),
|
||||||
mCommonParams(aCommonParams),
|
mCommonParams(aCommonParams),
|
||||||
|
mDirectoryLockId(-1),
|
||||||
mState(State::Initial),
|
mState(State::Initial),
|
||||||
mWaitingForPermissionRetry(false),
|
mWaitingForPermissionRetry(false),
|
||||||
mEnforcingQuota(true),
|
mEnforcingQuota(true),
|
||||||
|
@ -20042,11 +20048,15 @@ FactoryOp::Run() {
|
||||||
|
|
||||||
void FactoryOp::DirectoryLockAcquired(DirectoryLock* aLock) {
|
void FactoryOp::DirectoryLockAcquired(DirectoryLock* aLock) {
|
||||||
AssertIsOnOwningThread();
|
AssertIsOnOwningThread();
|
||||||
|
MOZ_ASSERT(aLock);
|
||||||
MOZ_ASSERT(mState == State::DirectoryOpenPending);
|
MOZ_ASSERT(mState == State::DirectoryOpenPending);
|
||||||
MOZ_ASSERT(!mDirectoryLock);
|
MOZ_ASSERT(!mDirectoryLock);
|
||||||
|
|
||||||
mDirectoryLock = aLock;
|
mDirectoryLock = aLock;
|
||||||
|
|
||||||
|
MOZ_ASSERT(mDirectoryLock->GetId() >= 0);
|
||||||
|
mDirectoryLockId = mDirectoryLock->GetId();
|
||||||
|
|
||||||
nsresult rv = DirectoryOpen();
|
nsresult rv = DirectoryOpen();
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
if (NS_SUCCEEDED(mResultCode)) {
|
if (NS_SUCCEEDED(mResultCode)) {
|
||||||
|
@ -20267,8 +20277,8 @@ nsresult OpenDatabaseOp::DoDatabaseWork() {
|
||||||
}
|
}
|
||||||
|
|
||||||
nsCOMPtr<mozIStorageConnection> connection;
|
nsCOMPtr<mozIStorageConnection> connection;
|
||||||
rv = CreateStorageConnection(dbFile, fmDirectory, databaseName,
|
rv = CreateStorageConnection(dbFile, fmDirectory, databaseName, mOrigin,
|
||||||
persistenceType, mGroup, mOrigin, mTelemetryId,
|
mDirectoryLockId, mTelemetryId,
|
||||||
getter_AddRefs(connection));
|
getter_AddRefs(connection));
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||||
return rv;
|
return rv;
|
||||||
|
|
|
@ -52,8 +52,6 @@ class FileManager final {
|
||||||
int64_t aId);
|
int64_t aId);
|
||||||
|
|
||||||
static nsresult InitDirectory(nsIFile* aDirectory, nsIFile* aDatabaseFile,
|
static nsresult InitDirectory(nsIFile* aDirectory, nsIFile* aDatabaseFile,
|
||||||
PersistenceType aPersistenceType,
|
|
||||||
const nsACString& aGroup,
|
|
||||||
const nsACString& aOrigin,
|
const nsACString& aOrigin,
|
||||||
uint32_t aTelemetryId);
|
uint32_t aTelemetryId);
|
||||||
|
|
||||||
|
|
|
@ -221,6 +221,8 @@ const char kProfileDoChangeTopic[] = "profile-do-change";
|
||||||
|
|
||||||
const int32_t kCacheVersion = 1;
|
const int32_t kCacheVersion = 1;
|
||||||
|
|
||||||
|
const int64_t kBypassDirectoryLockIdTableId = -1;
|
||||||
|
|
||||||
/******************************************************************************
|
/******************************************************************************
|
||||||
* SQLite functions
|
* SQLite functions
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
@ -671,6 +673,8 @@ class DirectoryLockImpl final : public DirectoryLock {
|
||||||
nsTArray<DirectoryLockImpl*> mBlocking;
|
nsTArray<DirectoryLockImpl*> mBlocking;
|
||||||
nsTArray<DirectoryLockImpl*> mBlockedOn;
|
nsTArray<DirectoryLockImpl*> mBlockedOn;
|
||||||
|
|
||||||
|
const int64_t mId;
|
||||||
|
|
||||||
const bool mExclusive;
|
const bool mExclusive;
|
||||||
|
|
||||||
// Internal quota manager operations use this flag to prevent directory lock
|
// Internal quota manager operations use this flag to prevent directory lock
|
||||||
|
@ -685,7 +689,8 @@ class DirectoryLockImpl final : public DirectoryLock {
|
||||||
const Nullable<PersistenceType>& aPersistenceType,
|
const Nullable<PersistenceType>& aPersistenceType,
|
||||||
const nsACString& aGroup, const OriginScope& aOriginScope,
|
const nsACString& aGroup, const OriginScope& aOriginScope,
|
||||||
const Nullable<Client::Type>& aClientType, bool aExclusive,
|
const Nullable<Client::Type>& aClientType, bool aExclusive,
|
||||||
bool aInternal, OpenDirectoryListener* aOpenListener);
|
bool aInternal, OpenDirectoryListener* aOpenListener,
|
||||||
|
const int64_t aDirectoryLockId);
|
||||||
|
|
||||||
void AssertIsOnOwningThread() const
|
void AssertIsOnOwningThread() const
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
|
@ -703,10 +708,26 @@ class DirectoryLockImpl final : public DirectoryLock {
|
||||||
|
|
||||||
const OriginScope& GetOriginScope() const { return mOriginScope; }
|
const OriginScope& GetOriginScope() const { return mOriginScope; }
|
||||||
|
|
||||||
|
const nsACString& GetOrigin() const {
|
||||||
|
MOZ_DIAGNOSTIC_ASSERT(GetOriginScope().IsOrigin());
|
||||||
|
return mOriginScope.GetOrigin();
|
||||||
|
}
|
||||||
|
|
||||||
const Nullable<Client::Type>& GetClientType() const { return mClientType; }
|
const Nullable<Client::Type>& GetClientType() const { return mClientType; }
|
||||||
|
|
||||||
|
int64_t GetId() const { return mId; }
|
||||||
|
|
||||||
bool IsInternal() const { return mInternal; }
|
bool IsInternal() const { return mInternal; }
|
||||||
|
|
||||||
|
// To evict inactive oirigins, we need to register directorylocks for that.
|
||||||
|
// However, since accessing the QuotaMnaager::mDirectoryLockIdTable
|
||||||
|
// require to acquire the mQuotaMutex and so does the accessing the
|
||||||
|
// originInfo. Therefore, we decide not to access the
|
||||||
|
// QuotaManager::mDirectoryLockIdTable for the internal DirectoryLock.
|
||||||
|
bool ShouldUpdateLockIdTable() const {
|
||||||
|
return mId != kBypassDirectoryLockIdTableId;
|
||||||
|
}
|
||||||
|
|
||||||
void SetRegistered(bool aRegistered) { mRegistered = aRegistered; }
|
void SetRegistered(bool aRegistered) { mRegistered = aRegistered; }
|
||||||
|
|
||||||
bool ShouldUpdateLockTable() {
|
bool ShouldUpdateLockTable() {
|
||||||
|
@ -2684,6 +2705,14 @@ bool RecvShutdownQuotaManager() {
|
||||||
* Directory lock
|
* Directory lock
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
|
const nsACString& DirectoryLock::GetOrigin() const {
|
||||||
|
return GetDirectoryLockImpl(this)->GetOrigin();
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t DirectoryLock::GetId() const {
|
||||||
|
return GetDirectoryLockImpl(this)->GetId();
|
||||||
|
}
|
||||||
|
|
||||||
already_AddRefed<DirectoryLock> DirectoryLock::Specialize(
|
already_AddRefed<DirectoryLock> DirectoryLock::Specialize(
|
||||||
PersistenceType aPersistenceType, const nsACString& aGroup,
|
PersistenceType aPersistenceType, const nsACString& aGroup,
|
||||||
const nsACString& aOrigin, Client::Type aClientType) const {
|
const nsACString& aOrigin, Client::Type aClientType) const {
|
||||||
|
@ -2697,13 +2726,15 @@ DirectoryLockImpl::DirectoryLockImpl(
|
||||||
QuotaManager* aQuotaManager,
|
QuotaManager* aQuotaManager,
|
||||||
const Nullable<PersistenceType>& aPersistenceType, const nsACString& aGroup,
|
const Nullable<PersistenceType>& aPersistenceType, const nsACString& aGroup,
|
||||||
const OriginScope& aOriginScope, const Nullable<Client::Type>& aClientType,
|
const OriginScope& aOriginScope, const Nullable<Client::Type>& aClientType,
|
||||||
bool aExclusive, bool aInternal, OpenDirectoryListener* aOpenListener)
|
bool aExclusive, bool aInternal, OpenDirectoryListener* aOpenListener,
|
||||||
|
const int64_t aId)
|
||||||
: mQuotaManager(aQuotaManager),
|
: mQuotaManager(aQuotaManager),
|
||||||
mPersistenceType(aPersistenceType),
|
mPersistenceType(aPersistenceType),
|
||||||
mGroup(aGroup),
|
mGroup(aGroup),
|
||||||
mOriginScope(aOriginScope),
|
mOriginScope(aOriginScope),
|
||||||
mClientType(aClientType),
|
mClientType(aClientType),
|
||||||
mOpenListener(aOpenListener),
|
mOpenListener(aOpenListener),
|
||||||
|
mId(aId),
|
||||||
mExclusive(aExclusive),
|
mExclusive(aExclusive),
|
||||||
mInternal(aInternal),
|
mInternal(aInternal),
|
||||||
mRegistered(false),
|
mRegistered(false),
|
||||||
|
@ -2811,6 +2842,7 @@ already_AddRefed<DirectoryLock> DirectoryLockImpl::Specialize(
|
||||||
MOZ_ASSERT(aClientType < Client::TypeMax());
|
MOZ_ASSERT(aClientType < Client::TypeMax());
|
||||||
MOZ_ASSERT(!mOpenListener);
|
MOZ_ASSERT(!mOpenListener);
|
||||||
MOZ_ASSERT(mBlockedOn.IsEmpty());
|
MOZ_ASSERT(mBlockedOn.IsEmpty());
|
||||||
|
MOZ_ASSERT(mQuotaManager);
|
||||||
|
|
||||||
if (NS_WARN_IF(mExclusive)) {
|
if (NS_WARN_IF(mExclusive)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -2819,7 +2851,8 @@ already_AddRefed<DirectoryLock> DirectoryLockImpl::Specialize(
|
||||||
RefPtr<DirectoryLockImpl> lock = new DirectoryLockImpl(
|
RefPtr<DirectoryLockImpl> lock = new DirectoryLockImpl(
|
||||||
mQuotaManager, Nullable<PersistenceType>(aPersistenceType), aGroup,
|
mQuotaManager, Nullable<PersistenceType>(aPersistenceType), aGroup,
|
||||||
OriginScope::FromOrigin(aOrigin), Nullable<Client::Type>(aClientType),
|
OriginScope::FromOrigin(aOrigin), Nullable<Client::Type>(aClientType),
|
||||||
/* aExclusive */ false, mInternal, /* aOpenListener */ nullptr);
|
/* aExclusive */ false, mInternal, /* aOpenListener */ nullptr,
|
||||||
|
mQuotaManager->GenerateDirectoryLockId());
|
||||||
|
|
||||||
if (NS_WARN_IF(!Overlaps(*lock))) {
|
if (NS_WARN_IF(!Overlaps(*lock))) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -3425,6 +3458,7 @@ QuotaManager::QuotaManager()
|
||||||
: mQuotaMutex("QuotaManager.mQuotaMutex"),
|
: mQuotaMutex("QuotaManager.mQuotaMutex"),
|
||||||
mTemporaryStorageLimit(0),
|
mTemporaryStorageLimit(0),
|
||||||
mTemporaryStorageUsage(0),
|
mTemporaryStorageUsage(0),
|
||||||
|
mNextDirectoryLockId(0),
|
||||||
mTemporaryStorageInitialized(false),
|
mTemporaryStorageInitialized(false),
|
||||||
mCacheUsable(false) {
|
mCacheUsable(false) {
|
||||||
AssertIsOnOwningThread();
|
AssertIsOnOwningThread();
|
||||||
|
@ -3532,9 +3566,9 @@ auto QuotaManager::CreateDirectoryLock(
|
||||||
MOZ_ASSERT_IF(!aInternal, aClientType.Value() < Client::TypeMax());
|
MOZ_ASSERT_IF(!aInternal, aClientType.Value() < Client::TypeMax());
|
||||||
MOZ_ASSERT_IF(!aInternal, aOpenListener);
|
MOZ_ASSERT_IF(!aInternal, aOpenListener);
|
||||||
|
|
||||||
RefPtr<DirectoryLockImpl> lock =
|
RefPtr<DirectoryLockImpl> lock = new DirectoryLockImpl(
|
||||||
new DirectoryLockImpl(this, aPersistenceType, aGroup, aOriginScope,
|
this, aPersistenceType, aGroup, aOriginScope, aClientType, aExclusive,
|
||||||
aClientType, aExclusive, aInternal, aOpenListener);
|
aInternal, aOpenListener, GenerateDirectoryLockId());
|
||||||
|
|
||||||
mPendingDirectoryLocks.AppendElement(lock);
|
mPendingDirectoryLocks.AppendElement(lock);
|
||||||
|
|
||||||
|
@ -3570,7 +3604,8 @@ auto QuotaManager::CreateDirectoryLockForEviction(
|
||||||
this, Nullable<PersistenceType>(aPersistenceType), aGroup,
|
this, Nullable<PersistenceType>(aPersistenceType), aGroup,
|
||||||
OriginScope::FromOrigin(aOrigin), Nullable<Client::Type>(),
|
OriginScope::FromOrigin(aOrigin), Nullable<Client::Type>(),
|
||||||
/* aExclusive */ true,
|
/* aExclusive */ true,
|
||||||
/* aInternal */ true, nullptr);
|
/* aInternal */ true, nullptr, /* aDirectoryLockId */
|
||||||
|
kBypassDirectoryLockIdTableId);
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
for (uint32_t index = mDirectoryLocks.Length(); index > 0; index--) {
|
for (uint32_t index = mDirectoryLocks.Length(); index > 0; index--) {
|
||||||
|
@ -3590,6 +3625,12 @@ void QuotaManager::RegisterDirectoryLock(DirectoryLockImpl* aLock) {
|
||||||
|
|
||||||
mDirectoryLocks.AppendElement(aLock);
|
mDirectoryLocks.AppendElement(aLock);
|
||||||
|
|
||||||
|
if (aLock->ShouldUpdateLockIdTable()) {
|
||||||
|
MutexAutoLock lock(mQuotaMutex);
|
||||||
|
|
||||||
|
mDirectoryLockIdTable.Put(aLock->GetId(), aLock);
|
||||||
|
}
|
||||||
|
|
||||||
if (aLock->ShouldUpdateLockTable()) {
|
if (aLock->ShouldUpdateLockTable()) {
|
||||||
const Nullable<PersistenceType>& persistenceType =
|
const Nullable<PersistenceType>& persistenceType =
|
||||||
aLock->GetPersistenceType();
|
aLock->GetPersistenceType();
|
||||||
|
@ -3621,9 +3662,17 @@ void QuotaManager::RegisterDirectoryLock(DirectoryLockImpl* aLock) {
|
||||||
|
|
||||||
void QuotaManager::UnregisterDirectoryLock(DirectoryLockImpl* aLock) {
|
void QuotaManager::UnregisterDirectoryLock(DirectoryLockImpl* aLock) {
|
||||||
AssertIsOnOwningThread();
|
AssertIsOnOwningThread();
|
||||||
|
MOZ_ASSERT(aLock);
|
||||||
|
|
||||||
MOZ_ALWAYS_TRUE(mDirectoryLocks.RemoveElement(aLock));
|
MOZ_ALWAYS_TRUE(mDirectoryLocks.RemoveElement(aLock));
|
||||||
|
|
||||||
|
if (aLock->ShouldUpdateLockIdTable()) {
|
||||||
|
MutexAutoLock lock(mQuotaMutex);
|
||||||
|
|
||||||
|
MOZ_DIAGNOSTIC_ASSERT(mDirectoryLockIdTable.Get(aLock->GetId()));
|
||||||
|
mDirectoryLockIdTable.Remove(aLock->GetId());
|
||||||
|
}
|
||||||
|
|
||||||
if (aLock->ShouldUpdateLockTable()) {
|
if (aLock->ShouldUpdateLockTable()) {
|
||||||
const Nullable<PersistenceType>& persistenceType =
|
const Nullable<PersistenceType>& persistenceType =
|
||||||
aLock->GetPersistenceType();
|
aLock->GetPersistenceType();
|
||||||
|
@ -4646,6 +4695,36 @@ already_AddRefed<QuotaObject> QuotaManager::GetQuotaObject(
|
||||||
aFileSize, aFileSizeOut);
|
aFileSize, aFileSizeOut);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
already_AddRefed<QuotaObject> QuotaManager::GetQuotaObject(
|
||||||
|
const int64_t aDirectoryLockId, const nsAString& aPath) {
|
||||||
|
NS_ASSERTION(!NS_IsMainThread(), "Wrong thread!");
|
||||||
|
MOZ_DIAGNOSTIC_ASSERT(aDirectoryLockId != kBypassDirectoryLockIdTableId);
|
||||||
|
|
||||||
|
Maybe<MutexAutoLock> lock;
|
||||||
|
if (!IsOnBackgroundThread()) {
|
||||||
|
lock.emplace(mQuotaMutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
DirectoryLockImpl* directoryLock;
|
||||||
|
if (!mDirectoryLockIdTable.Get(aDirectoryLockId, &directoryLock)) {
|
||||||
|
MOZ_CRASH("Getting quota object for an unregistered directory lock?");
|
||||||
|
}
|
||||||
|
|
||||||
|
MOZ_DIAGNOSTIC_ASSERT(directoryLock);
|
||||||
|
MOZ_DIAGNOSTIC_ASSERT(!directoryLock->GetPersistenceType().IsNull());
|
||||||
|
PersistenceType persistenceType = directoryLock->GetPersistenceType().Value();
|
||||||
|
|
||||||
|
nsCString group(directoryLock->GetGroup());
|
||||||
|
nsCString origin(directoryLock->GetOrigin());
|
||||||
|
|
||||||
|
MOZ_DIAGNOSTIC_ASSERT(!directoryLock->GetClientType().IsNull());
|
||||||
|
Client::Type clientType = directoryLock->GetClientType().Value();
|
||||||
|
|
||||||
|
lock.reset();
|
||||||
|
|
||||||
|
return GetQuotaObject(persistenceType, group, origin, clientType, aPath);
|
||||||
|
}
|
||||||
|
|
||||||
Nullable<bool> QuotaManager::OriginPersisted(const nsACString& aGroup,
|
Nullable<bool> QuotaManager::OriginPersisted(const nsACString& aGroup,
|
||||||
const nsACString& aOrigin) {
|
const nsACString& aOrigin) {
|
||||||
AssertIsOnIOThread();
|
AssertIsOnIOThread();
|
||||||
|
@ -7600,6 +7679,22 @@ bool QuotaManager::IsSanitizedOriginValid(const nsACString& aSanitizedOrigin) {
|
||||||
return valid;
|
return valid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int64_t QuotaManager::GenerateDirectoryLockId() {
|
||||||
|
const int64_t directroylockId = mNextDirectoryLockId;
|
||||||
|
|
||||||
|
CheckedInt64 result = CheckedInt64(mNextDirectoryLockId) + 1;
|
||||||
|
if (result.isValid()) {
|
||||||
|
mNextDirectoryLockId = result.value();
|
||||||
|
} else {
|
||||||
|
// When this happens, it means we have run out of ids for directory locks.
|
||||||
|
// To avoid something unexpected happen and assuming there shouldn't have
|
||||||
|
// INT64_MAX directorylock exist at the same time, we reset the id here.
|
||||||
|
mNextDirectoryLockId = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return directroylockId;
|
||||||
|
}
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
* Local class implementations
|
* Local class implementations
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
|
@ -63,6 +63,10 @@ class DirectoryLock : public RefCountedObject {
|
||||||
friend class DirectoryLockImpl;
|
friend class DirectoryLockImpl;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
const nsACString& GetOrigin() const;
|
||||||
|
|
||||||
|
int64_t GetId() const;
|
||||||
|
|
||||||
already_AddRefed<DirectoryLock> Specialize(PersistenceType aPersistenceType,
|
already_AddRefed<DirectoryLock> Specialize(PersistenceType aPersistenceType,
|
||||||
const nsACString& aGroup,
|
const nsACString& aGroup,
|
||||||
const nsACString& aOrigin,
|
const nsACString& aOrigin,
|
||||||
|
@ -232,6 +236,9 @@ class QuotaManager final : public BackgroundThreadObject {
|
||||||
int64_t aFileSize = -1,
|
int64_t aFileSize = -1,
|
||||||
int64_t* aFileSizeOut = nullptr);
|
int64_t* aFileSizeOut = nullptr);
|
||||||
|
|
||||||
|
already_AddRefed<QuotaObject> GetQuotaObject(const int64_t aDirectoryLockId,
|
||||||
|
const nsAString& aPath);
|
||||||
|
|
||||||
Nullable<bool> OriginPersisted(const nsACString& aGroup,
|
Nullable<bool> OriginPersisted(const nsACString& aGroup,
|
||||||
const nsACString& aOrigin);
|
const nsACString& aOrigin);
|
||||||
|
|
||||||
|
@ -545,6 +552,8 @@ class QuotaManager final : public BackgroundThreadObject {
|
||||||
|
|
||||||
bool IsSanitizedOriginValid(const nsACString& aSanitizedOrigin);
|
bool IsSanitizedOriginValid(const nsACString& aSanitizedOrigin);
|
||||||
|
|
||||||
|
int64_t GenerateDirectoryLockId();
|
||||||
|
|
||||||
static void ShutdownTimerCallback(nsITimer* aTimer, void* aClosure);
|
static void ShutdownTimerCallback(nsITimer* aTimer, void* aClosure);
|
||||||
|
|
||||||
// Thread on which IO is performed.
|
// Thread on which IO is performed.
|
||||||
|
@ -562,9 +571,16 @@ class QuotaManager final : public BackgroundThreadObject {
|
||||||
// Maintains a list of directory locks that are queued.
|
// Maintains a list of directory locks that are queued.
|
||||||
nsTArray<RefPtr<DirectoryLockImpl>> mPendingDirectoryLocks;
|
nsTArray<RefPtr<DirectoryLockImpl>> mPendingDirectoryLocks;
|
||||||
|
|
||||||
// Maintains a list of directory locks that are acquired or queued.
|
// Maintains a list of directory locks that are acquired or queued. It can be
|
||||||
|
// accessed on the owning (PBackground) thread only.
|
||||||
nsTArray<DirectoryLockImpl*> mDirectoryLocks;
|
nsTArray<DirectoryLockImpl*> mDirectoryLocks;
|
||||||
|
|
||||||
|
// Only modifed on the owning thread, but read on multiple threads. Therefore
|
||||||
|
// all modifications (including those on the owning thread) and all reads off
|
||||||
|
// the owning thread must be protected by mQuotaMutex. In other words, only
|
||||||
|
// reads on the owning thread don't have to be protected by mQuotaMutex.
|
||||||
|
nsDataHashtable<nsUint64HashKey, DirectoryLockImpl*> mDirectoryLockIdTable;
|
||||||
|
|
||||||
// Directory lock tables that are used to update origin access time.
|
// Directory lock tables that are used to update origin access time.
|
||||||
DirectoryLockTable mTemporaryDirectoryLockTable;
|
DirectoryLockTable mTemporaryDirectoryLockTable;
|
||||||
DirectoryLockTable mDefaultDirectoryLockTable;
|
DirectoryLockTable mDefaultDirectoryLockTable;
|
||||||
|
@ -594,6 +610,7 @@ class QuotaManager final : public BackgroundThreadObject {
|
||||||
|
|
||||||
uint64_t mTemporaryStorageLimit;
|
uint64_t mTemporaryStorageLimit;
|
||||||
uint64_t mTemporaryStorageUsage;
|
uint64_t mTemporaryStorageUsage;
|
||||||
|
int64_t mNextDirectoryLockId;
|
||||||
bool mTemporaryStorageInitialized;
|
bool mTemporaryStorageInitialized;
|
||||||
bool mCacheUsable;
|
bool mCacheUsable;
|
||||||
};
|
};
|
||||||
|
|
|
@ -299,57 +299,22 @@ already_AddRefed<QuotaObject> GetQuotaObjectFromNameAndParameters(
|
||||||
MOZ_ASSERT(zName);
|
MOZ_ASSERT(zName);
|
||||||
MOZ_ASSERT(zURIParameterKey);
|
MOZ_ASSERT(zURIParameterKey);
|
||||||
|
|
||||||
const char* persistenceType =
|
const char* directoryLockIdParam =
|
||||||
sqlite3_uri_parameter(zURIParameterKey, "persistenceType");
|
sqlite3_uri_parameter(zURIParameterKey, "directoryLockId");
|
||||||
if (!persistenceType) {
|
if (!directoryLockIdParam) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* group = sqlite3_uri_parameter(zURIParameterKey, "group");
|
nsresult rv;
|
||||||
if (!group) {
|
const int64_t directoryLockId =
|
||||||
NS_WARNING("SQLite URI had 'persistenceType' but not 'group'?!");
|
nsDependentCString(directoryLockIdParam).ToInteger64(&rv);
|
||||||
return nullptr;
|
MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
|
||||||
}
|
|
||||||
|
|
||||||
const char* origin = sqlite3_uri_parameter(zURIParameterKey, "origin");
|
|
||||||
if (!origin) {
|
|
||||||
NS_WARNING(
|
|
||||||
"SQLite URI had 'persistenceType' and 'group' but not "
|
|
||||||
"'origin'?!");
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* clientType =
|
|
||||||
sqlite3_uri_parameter(zURIParameterKey, "clientType");
|
|
||||||
if (!clientType) {
|
|
||||||
NS_WARNING(
|
|
||||||
"SQLite URI had 'persistenceType', 'group' and 'origin' but not "
|
|
||||||
"'clientType'?!");
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Re-escape group and origin to make sure we get the right quota group and
|
|
||||||
// origin.
|
|
||||||
nsAutoCString escGroup;
|
|
||||||
nsresult rv =
|
|
||||||
NS_EscapeURL(nsDependentCString(group), esc_Query, escGroup, fallible);
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsAutoCString escOrigin;
|
|
||||||
rv = NS_EscapeURL(nsDependentCString(origin), esc_Query, escOrigin, fallible);
|
|
||||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
QuotaManager* quotaManager = QuotaManager::Get();
|
QuotaManager* quotaManager = QuotaManager::Get();
|
||||||
MOZ_ASSERT(quotaManager);
|
MOZ_ASSERT(quotaManager);
|
||||||
|
|
||||||
return quotaManager->GetQuotaObject(
|
return quotaManager->GetQuotaObject(directoryLockId,
|
||||||
PersistenceTypeFromText(nsDependentCString(persistenceType)), escGroup,
|
NS_ConvertUTF8toUTF16(zName));
|
||||||
escOrigin, Client::TypeFromText(nsDependentCString(clientType)),
|
|
||||||
NS_ConvertUTF8toUTF16(zName));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void MaybeEstablishQuotaControl(const char* zName, telemetry_file* pFile,
|
void MaybeEstablishQuotaControl(const char* zName, telemetry_file* pFile,
|
||||||
|
|
Загрузка…
Ссылка в новой задаче