зеркало из 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) {
|
||||
NS_ASSERT_OWNINGTHREAD(QuotaInitRunnable);
|
||||
MOZ_DIAGNOSTIC_ASSERT(aLock);
|
||||
MOZ_DIAGNOSTIC_ASSERT(mState == STATE_WAIT_FOR_DIRECTORY_LOCK);
|
||||
MOZ_DIAGNOSTIC_ASSERT(!mDirectoryLock);
|
||||
|
||||
mDirectoryLock = aLock;
|
||||
|
||||
MOZ_DIAGNOSTIC_ASSERT(mDirectoryLock->GetId() >= 0);
|
||||
mQuotaInfo.mDirectoryLockId = mDirectoryLock->GetId();
|
||||
|
||||
if (mCanceled) {
|
||||
Complete(NS_ERROR_ABORT);
|
||||
return;
|
||||
|
|
|
@ -27,6 +27,7 @@ namespace cache {
|
|||
|
||||
using mozilla::dom::quota::AssertIsOnIOThread;
|
||||
using mozilla::dom::quota::Client;
|
||||
using mozilla::dom::quota::IntCString;
|
||||
using mozilla::dom::quota::PERSISTENCE_TYPE_DEFAULT;
|
||||
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,
|
||||
mozIStorageConnection** aConnOut) {
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
MOZ_DIAGNOSTIC_ASSERT(aQuotaInfo.mDirectoryLockId >= 0);
|
||||
MOZ_DIAGNOSTIC_ASSERT(aDBDir);
|
||||
MOZ_DIAGNOSTIC_ASSERT(aConnOut);
|
||||
|
||||
|
@ -168,6 +170,7 @@ void SyncDBAction::RunWithDBOnTarget(Resolver* aResolver,
|
|||
nsresult OpenDBConnection(const QuotaInfo& aQuotaInfo, nsIFile* aDBDir,
|
||||
mozIStorageConnection** aConnOut) {
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
MOZ_DIAGNOSTIC_ASSERT(aQuotaInfo.mDirectoryLockId >= -1);
|
||||
MOZ_DIAGNOSTIC_ASSERT(aDBDir);
|
||||
MOZ_DIAGNOSTIC_ASSERT(aConnOut);
|
||||
|
||||
|
@ -208,18 +211,15 @@ nsresult OpenDBConnection(const QuotaInfo& aQuotaInfo, nsIFile* aDBDir,
|
|||
|
||||
nsCOMPtr<nsIFileURL> dbFileUrl;
|
||||
|
||||
nsAutoCString type;
|
||||
PersistenceTypeToText(PERSISTENCE_TYPE_DEFAULT, type);
|
||||
const nsCString directoryLockIdClause =
|
||||
aQuotaInfo.mDirectoryLockId >= 0
|
||||
? NS_LITERAL_CSTRING("&directoryLockId=") +
|
||||
IntCString(aQuotaInfo.mDirectoryLockId)
|
||||
: EmptyCString();
|
||||
|
||||
nsAutoCString clientType;
|
||||
Client::TypeToText(Client::DOMCACHE, clientType);
|
||||
|
||||
rv = NS_MutateURI(mutator)
|
||||
.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"))
|
||||
rv =
|
||||
NS_MutateURI(mutator)
|
||||
.SetQuery(NS_LITERAL_CSTRING("cache=private") + directoryLockIdClause)
|
||||
.Finalize(dbFileUrl);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
|
|
|
@ -40,7 +40,7 @@ class DBAction : public Action {
|
|||
mozIStorageConnection* aConn) = 0;
|
||||
|
||||
private:
|
||||
virtual void RunOnTarget(Resolver* aResolver, const QuotaInfo& aQuotaInfo,
|
||||
void RunOnTarget(Resolver* aResolver, const QuotaInfo& aQuotaInfo,
|
||||
Data* aOptionalData) override;
|
||||
|
||||
nsresult OpenConnection(const QuotaInfo& aQuotaInfo, nsIFile* aQuotaDir,
|
||||
|
|
|
@ -148,7 +148,7 @@ class DeleteOrphanedBodyAction final : public Action {
|
|||
mDeletedBodyIdList.AppendElement(aBodyId);
|
||||
}
|
||||
|
||||
virtual void RunOnTarget(Resolver* aResolver, const QuotaInfo& aQuotaInfo,
|
||||
void RunOnTarget(Resolver* aResolver, const QuotaInfo& aQuotaInfo,
|
||||
Data*) override {
|
||||
MOZ_DIAGNOSTIC_ASSERT(aResolver);
|
||||
MOZ_DIAGNOSTIC_ASSERT(aQuotaInfo.mDir);
|
||||
|
|
|
@ -115,6 +115,11 @@ static nsresult LockedGetPaddingSizeFromDB(nsIFile* aDir,
|
|||
QuotaInfo quotaInfo;
|
||||
quotaInfo.mGroup = aGroup;
|
||||
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,
|
||||
getter_AddRefs(conn));
|
||||
if (rv == NS_ERROR_FILE_NOT_FOUND ||
|
||||
|
@ -432,12 +437,25 @@ class CacheQuotaClient final : public Client {
|
|||
dir, DirPaddingFile::TMP_FILE) ||
|
||||
NS_WARN_IF(NS_FAILED(mozilla::dom::cache::LockedDirectoryPaddingGet(
|
||||
dir, &paddingSize)))) {
|
||||
if (aInitializing) {
|
||||
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,
|
||||
Cache_GetPaddingSize);
|
||||
|
||||
return NS_ERROR_ABORT;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -33,6 +33,9 @@ struct QuotaInfo {
|
|||
nsCString mSuffix;
|
||||
nsCString mGroup;
|
||||
nsCString mOrigin;
|
||||
int64_t mDirectoryLockId;
|
||||
|
||||
QuotaInfo() : mDirectoryLockId(-1) {}
|
||||
};
|
||||
|
||||
typedef std::function<void(nsCOMPtr<nsIInputStream>&&)> InputStreamResolver;
|
||||
|
|
|
@ -3898,9 +3898,7 @@ nsresult UpgradeSchemaFrom25_0To26_0(mozIStorageConnection* aConnection) {
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult GetDatabaseFileURL(nsIFile* aDatabaseFile,
|
||||
PersistenceType aPersistenceType,
|
||||
const nsACString& aGroup, const nsACString& aOrigin,
|
||||
nsresult GetDatabaseFileURL(nsIFile* aDatabaseFile, int64_t aDirectoryLockId,
|
||||
uint32_t aTelemetryId, nsIFileURL** aResult) {
|
||||
MOZ_ASSERT(aDatabaseFile);
|
||||
MOZ_ASSERT(aResult);
|
||||
|
@ -3927,11 +3925,14 @@ nsresult GetDatabaseFileURL(nsIFile* aDatabaseFile,
|
|||
|
||||
nsCOMPtr<nsIFileURL> fileUrl;
|
||||
|
||||
nsAutoCString type;
|
||||
PersistenceTypeToText(aPersistenceType, type);
|
||||
|
||||
nsAutoCString clientType;
|
||||
Client::TypeToText(Client::IDB, clientType);
|
||||
// The aDirectoryLock should only be a nullptr when the temporary storage
|
||||
// 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
|
||||
// directoryLockId to TelemetryVFS to get the quotaObject.
|
||||
const nsCString directoryLockIdClause =
|
||||
aDirectoryLockId >= 0 ? NS_LITERAL_CSTRING("&directoryLockId=") +
|
||||
IntCString(aDirectoryLockId)
|
||||
: EmptyCString();
|
||||
|
||||
nsAutoCString telemetryFilenameClause;
|
||||
if (aTelemetryId) {
|
||||
|
@ -3941,12 +3942,8 @@ nsresult GetDatabaseFileURL(nsIFile* aDatabaseFile,
|
|||
}
|
||||
|
||||
rv = NS_MutateURI(mutator)
|
||||
.SetQuery(NS_LITERAL_CSTRING("persistenceType=") + type +
|
||||
NS_LITERAL_CSTRING("&group=") + aGroup +
|
||||
NS_LITERAL_CSTRING("&origin=") + aOrigin +
|
||||
NS_LITERAL_CSTRING("&clientType=") + clientType +
|
||||
NS_LITERAL_CSTRING("&cache=private") +
|
||||
telemetryFilenameClause)
|
||||
.SetQuery(NS_LITERAL_CSTRING("cache=private") +
|
||||
directoryLockIdClause + telemetryFilenameClause)
|
||||
.Finalize(fileUrl);
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
|
@ -4167,14 +4164,14 @@ nsresult OpenDatabaseAndHandleBusy(mozIStorageService* aStorageService,
|
|||
|
||||
nsresult CreateStorageConnection(nsIFile* aDBFile, nsIFile* aFMDirectory,
|
||||
const nsAString& aName,
|
||||
PersistenceType aPersistenceType,
|
||||
const nsACString& aGroup,
|
||||
const nsACString& aOrigin,
|
||||
int64_t aDirectoryLockId,
|
||||
uint32_t aTelemetryId,
|
||||
mozIStorageConnection** aConnection) {
|
||||
AssertIsOnIOThread();
|
||||
MOZ_ASSERT(aDBFile);
|
||||
MOZ_ASSERT(aFMDirectory);
|
||||
MOZ_ASSERT(aDirectoryLockId >= -1);
|
||||
MOZ_ASSERT(aConnection);
|
||||
|
||||
AUTO_PROFILER_LABEL("CreateStorageConnection", DOM);
|
||||
|
@ -4183,8 +4180,8 @@ nsresult CreateStorageConnection(nsIFile* aDBFile, nsIFile* aFMDirectory,
|
|||
bool exists;
|
||||
|
||||
nsCOMPtr<nsIFileURL> dbFileUrl;
|
||||
rv = GetDatabaseFileURL(aDBFile, aPersistenceType, aGroup, aOrigin,
|
||||
aTelemetryId, getter_AddRefs(dbFileUrl));
|
||||
rv = GetDatabaseFileURL(aDBFile, aDirectoryLockId, aTelemetryId,
|
||||
getter_AddRefs(dbFileUrl));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -4629,14 +4626,13 @@ already_AddRefed<nsIFile> GetFileForPath(const nsAString& aPath) {
|
|||
return file.forget();
|
||||
}
|
||||
|
||||
nsresult GetStorageConnection(nsIFile* aDatabaseFile,
|
||||
PersistenceType aPersistenceType,
|
||||
const nsACString& aGroup,
|
||||
const nsACString& aOrigin, uint32_t aTelemetryId,
|
||||
nsresult GetStorageConnection(nsIFile* aDatabaseFile, int64_t aDirectoryLockId,
|
||||
uint32_t aTelemetryId,
|
||||
mozIStorageConnection** aConnection) {
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
MOZ_ASSERT(!IsOnBackgroundThread());
|
||||
MOZ_ASSERT(aDatabaseFile);
|
||||
MOZ_ASSERT(aDirectoryLockId >= 0);
|
||||
MOZ_ASSERT(aConnection);
|
||||
|
||||
AUTO_PROFILER_LABEL("GetStorageConnection", DOM);
|
||||
|
@ -4653,8 +4649,8 @@ nsresult GetStorageConnection(nsIFile* aDatabaseFile,
|
|||
}
|
||||
|
||||
nsCOMPtr<nsIFileURL> dbFileUrl;
|
||||
rv = GetDatabaseFileURL(aDatabaseFile, aPersistenceType, aGroup, aOrigin,
|
||||
aTelemetryId, getter_AddRefs(dbFileUrl));
|
||||
rv = GetDatabaseFileURL(aDatabaseFile, aDirectoryLockId, aTelemetryId,
|
||||
getter_AddRefs(dbFileUrl));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -4686,14 +4682,13 @@ nsresult GetStorageConnection(nsIFile* aDatabaseFile,
|
|||
}
|
||||
|
||||
nsresult GetStorageConnection(const nsAString& aDatabaseFilePath,
|
||||
PersistenceType aPersistenceType,
|
||||
const nsACString& aGroup,
|
||||
const nsACString& aOrigin, uint32_t aTelemetryId,
|
||||
int64_t aDirectoryLockId, uint32_t aTelemetryId,
|
||||
mozIStorageConnection** aConnection) {
|
||||
MOZ_ASSERT(!NS_IsMainThread());
|
||||
MOZ_ASSERT(!IsOnBackgroundThread());
|
||||
MOZ_ASSERT(!aDatabaseFilePath.IsEmpty());
|
||||
MOZ_ASSERT(StringEndsWith(aDatabaseFilePath, kSQLiteSuffix));
|
||||
MOZ_ASSERT(aDirectoryLockId >= 0);
|
||||
MOZ_ASSERT(aConnection);
|
||||
|
||||
nsCOMPtr<nsIFile> dbFile = GetFileForPath(aDatabaseFilePath);
|
||||
|
@ -4702,8 +4697,8 @@ nsresult GetStorageConnection(const nsAString& aDatabaseFilePath,
|
|||
return NS_ERROR_DOM_INDEXEDDB_UNKNOWN_ERR;
|
||||
}
|
||||
|
||||
return GetStorageConnection(dbFile, aPersistenceType, aGroup, aOrigin,
|
||||
aTelemetryId, aConnection);
|
||||
return GetStorageConnection(dbFile, aDirectoryLockId, aTelemetryId,
|
||||
aConnection);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
@ -5796,6 +5791,7 @@ class Database final
|
|||
const nsCString mId;
|
||||
const nsString mFilePath;
|
||||
uint32_t mActiveMutableFileCount;
|
||||
int64_t mDirectoryLockId;
|
||||
const uint32_t mTelemetryId;
|
||||
const PersistenceType mPersistenceType;
|
||||
const bool mFileHandleDisabled;
|
||||
|
@ -5846,6 +5842,8 @@ class Database final
|
|||
|
||||
const nsCString& Id() const { return mId; }
|
||||
|
||||
int64_t DirectoryLockId() const { return mDirectoryLockId; }
|
||||
|
||||
uint32_t TelemetryId() const { return mTelemetryId; }
|
||||
|
||||
PersistenceType Type() const { return mPersistenceType; }
|
||||
|
@ -6672,6 +6670,7 @@ class FactoryOp
|
|||
nsCString mOrigin;
|
||||
nsCString mDatabaseId;
|
||||
nsString mDatabaseFilePath;
|
||||
int64_t mDirectoryLockId;
|
||||
State mState;
|
||||
bool mWaitingForPermissionRetry;
|
||||
bool mEnforcingQuota;
|
||||
|
@ -8333,6 +8332,7 @@ class DatabaseMaintenance final : public Runnable {
|
|||
const nsCString mGroup;
|
||||
const nsCString mOrigin;
|
||||
const nsString mDatabasePath;
|
||||
int64_t mDirectoryLockId;
|
||||
nsCOMPtr<nsIRunnable> mCompleteCallback;
|
||||
const PersistenceType mPersistenceType;
|
||||
|
||||
|
@ -8346,7 +8346,12 @@ class DatabaseMaintenance final : public Runnable {
|
|||
mGroup(aGroup),
|
||||
mOrigin(aOrigin),
|
||||
mDatabasePath(aDatabasePath),
|
||||
mPersistenceType(aPersistenceType) {}
|
||||
mPersistenceType(aPersistenceType) {
|
||||
MOZ_ASSERT(aDirectoryLock);
|
||||
|
||||
MOZ_ASSERT(mDirectoryLock->GetId() >= 0);
|
||||
mDirectoryLockId = mDirectoryLock->GetId();
|
||||
}
|
||||
|
||||
const nsString& DatabasePath() const { return mDatabasePath; }
|
||||
|
||||
|
@ -10910,10 +10915,9 @@ nsresult ConnectionPool::GetOrCreateConnection(
|
|||
MOZ_ASSERT(!dbInfo->mDEBUGConnectionThread);
|
||||
|
||||
nsCOMPtr<mozIStorageConnection> storageConnection;
|
||||
nsresult rv = GetStorageConnection(aDatabase->FilePath(), aDatabase->Type(),
|
||||
aDatabase->Group(), aDatabase->Origin(),
|
||||
aDatabase->TelemetryId(),
|
||||
getter_AddRefs(storageConnection));
|
||||
nsresult rv = GetStorageConnection(
|
||||
aDatabase->FilePath(), aDatabase->DirectoryLockId(),
|
||||
aDatabase->TelemetryId(), getter_AddRefs(storageConnection));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
}
|
||||
|
@ -12598,6 +12602,10 @@ Database::Database(Factory* aFactory, const PrincipalInfo& aPrincipalInfo,
|
|||
MOZ_ASSERT(aFileManager);
|
||||
MOZ_ASSERT_IF(aChromeWriteAccessAllowed,
|
||||
aPrincipalInfo.type() == PrincipalInfo::TSystemPrincipalInfo);
|
||||
|
||||
MOZ_ASSERT(mDirectoryLock);
|
||||
MOZ_ASSERT(mDirectoryLock->GetId() >= 0);
|
||||
mDirectoryLockId = mDirectoryLock->GetId();
|
||||
}
|
||||
|
||||
void Database::Invalidate() {
|
||||
|
@ -15614,8 +15622,6 @@ already_AddRefed<nsIFile> FileManager::GetCheckedFileForId(nsIFile* aDirectory,
|
|||
|
||||
// static
|
||||
nsresult FileManager::InitDirectory(nsIFile* aDirectory, nsIFile* aDatabaseFile,
|
||||
PersistenceType aPersistenceType,
|
||||
const nsACString& aGroup,
|
||||
const nsACString& aOrigin,
|
||||
uint32_t aTelemetryId) {
|
||||
AssertIsOnIOThread();
|
||||
|
@ -15683,7 +15689,7 @@ nsresult FileManager::InitDirectory(nsIFile* aDirectory, nsIFile* aDatabaseFile,
|
|||
if (hasElements) {
|
||||
nsCOMPtr<mozIStorageConnection> connection;
|
||||
rv = CreateStorageConnection(aDatabaseFile, aDirectory, VoidString(),
|
||||
aPersistenceType, aGroup, aOrigin,
|
||||
aOrigin, /* aDirectoryLockId */ -1,
|
||||
aTelemetryId, getter_AddRefs(connection));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
|
@ -16224,8 +16230,7 @@ nsresult QuotaClient::InitOrigin(PersistenceType aPersistenceType,
|
|||
}
|
||||
}
|
||||
|
||||
rv = FileManager::InitDirectory(fmDirectory, databaseFile, aPersistenceType,
|
||||
aGroup, aOrigin,
|
||||
rv = FileManager::InitDirectory(fmDirectory, databaseFile, aOrigin,
|
||||
TelemetryIdForFile(databaseFile));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
REPORT_TELEMETRY_INIT_ERR(kQuotaInternalError, IDB_InitDirectory);
|
||||
|
@ -17612,8 +17617,8 @@ void DatabaseMaintenance::PerformMaintenanceOnDatabase() {
|
|||
MOZ_ASSERT(databaseFile);
|
||||
|
||||
nsCOMPtr<mozIStorageConnection> connection;
|
||||
nsresult rv = GetStorageConnection(databaseFile, mPersistenceType, mGroup,
|
||||
mOrigin, TelemetryIdForFile(databaseFile),
|
||||
nsresult rv = GetStorageConnection(databaseFile, mDirectoryLockId,
|
||||
TelemetryIdForFile(databaseFile),
|
||||
getter_AddRefs(connection));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return;
|
||||
|
@ -19294,6 +19299,7 @@ FactoryOp::FactoryOp(Factory* aFactory,
|
|||
mFactory(aFactory),
|
||||
mContentParent(std::move(aContentParent)),
|
||||
mCommonParams(aCommonParams),
|
||||
mDirectoryLockId(-1),
|
||||
mState(State::Initial),
|
||||
mWaitingForPermissionRetry(false),
|
||||
mEnforcingQuota(true),
|
||||
|
@ -20042,11 +20048,15 @@ FactoryOp::Run() {
|
|||
|
||||
void FactoryOp::DirectoryLockAcquired(DirectoryLock* aLock) {
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(aLock);
|
||||
MOZ_ASSERT(mState == State::DirectoryOpenPending);
|
||||
MOZ_ASSERT(!mDirectoryLock);
|
||||
|
||||
mDirectoryLock = aLock;
|
||||
|
||||
MOZ_ASSERT(mDirectoryLock->GetId() >= 0);
|
||||
mDirectoryLockId = mDirectoryLock->GetId();
|
||||
|
||||
nsresult rv = DirectoryOpen();
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
if (NS_SUCCEEDED(mResultCode)) {
|
||||
|
@ -20267,8 +20277,8 @@ nsresult OpenDatabaseOp::DoDatabaseWork() {
|
|||
}
|
||||
|
||||
nsCOMPtr<mozIStorageConnection> connection;
|
||||
rv = CreateStorageConnection(dbFile, fmDirectory, databaseName,
|
||||
persistenceType, mGroup, mOrigin, mTelemetryId,
|
||||
rv = CreateStorageConnection(dbFile, fmDirectory, databaseName, mOrigin,
|
||||
mDirectoryLockId, mTelemetryId,
|
||||
getter_AddRefs(connection));
|
||||
if (NS_WARN_IF(NS_FAILED(rv))) {
|
||||
return rv;
|
||||
|
|
|
@ -52,8 +52,6 @@ class FileManager final {
|
|||
int64_t aId);
|
||||
|
||||
static nsresult InitDirectory(nsIFile* aDirectory, nsIFile* aDatabaseFile,
|
||||
PersistenceType aPersistenceType,
|
||||
const nsACString& aGroup,
|
||||
const nsACString& aOrigin,
|
||||
uint32_t aTelemetryId);
|
||||
|
||||
|
|
|
@ -221,6 +221,8 @@ const char kProfileDoChangeTopic[] = "profile-do-change";
|
|||
|
||||
const int32_t kCacheVersion = 1;
|
||||
|
||||
const int64_t kBypassDirectoryLockIdTableId = -1;
|
||||
|
||||
/******************************************************************************
|
||||
* SQLite functions
|
||||
******************************************************************************/
|
||||
|
@ -671,6 +673,8 @@ class DirectoryLockImpl final : public DirectoryLock {
|
|||
nsTArray<DirectoryLockImpl*> mBlocking;
|
||||
nsTArray<DirectoryLockImpl*> mBlockedOn;
|
||||
|
||||
const int64_t mId;
|
||||
|
||||
const bool mExclusive;
|
||||
|
||||
// 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 nsACString& aGroup, const OriginScope& aOriginScope,
|
||||
const Nullable<Client::Type>& aClientType, bool aExclusive,
|
||||
bool aInternal, OpenDirectoryListener* aOpenListener);
|
||||
bool aInternal, OpenDirectoryListener* aOpenListener,
|
||||
const int64_t aDirectoryLockId);
|
||||
|
||||
void AssertIsOnOwningThread() const
|
||||
#ifdef DEBUG
|
||||
|
@ -703,10 +708,26 @@ class DirectoryLockImpl final : public DirectoryLock {
|
|||
|
||||
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; }
|
||||
|
||||
int64_t GetId() const { return mId; }
|
||||
|
||||
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; }
|
||||
|
||||
bool ShouldUpdateLockTable() {
|
||||
|
@ -2684,6 +2705,14 @@ bool RecvShutdownQuotaManager() {
|
|||
* 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(
|
||||
PersistenceType aPersistenceType, const nsACString& aGroup,
|
||||
const nsACString& aOrigin, Client::Type aClientType) const {
|
||||
|
@ -2697,13 +2726,15 @@ DirectoryLockImpl::DirectoryLockImpl(
|
|||
QuotaManager* aQuotaManager,
|
||||
const Nullable<PersistenceType>& aPersistenceType, const nsACString& aGroup,
|
||||
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),
|
||||
mPersistenceType(aPersistenceType),
|
||||
mGroup(aGroup),
|
||||
mOriginScope(aOriginScope),
|
||||
mClientType(aClientType),
|
||||
mOpenListener(aOpenListener),
|
||||
mId(aId),
|
||||
mExclusive(aExclusive),
|
||||
mInternal(aInternal),
|
||||
mRegistered(false),
|
||||
|
@ -2811,6 +2842,7 @@ already_AddRefed<DirectoryLock> DirectoryLockImpl::Specialize(
|
|||
MOZ_ASSERT(aClientType < Client::TypeMax());
|
||||
MOZ_ASSERT(!mOpenListener);
|
||||
MOZ_ASSERT(mBlockedOn.IsEmpty());
|
||||
MOZ_ASSERT(mQuotaManager);
|
||||
|
||||
if (NS_WARN_IF(mExclusive)) {
|
||||
return nullptr;
|
||||
|
@ -2819,7 +2851,8 @@ already_AddRefed<DirectoryLock> DirectoryLockImpl::Specialize(
|
|||
RefPtr<DirectoryLockImpl> lock = new DirectoryLockImpl(
|
||||
mQuotaManager, Nullable<PersistenceType>(aPersistenceType), aGroup,
|
||||
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))) {
|
||||
return nullptr;
|
||||
|
@ -3425,6 +3458,7 @@ QuotaManager::QuotaManager()
|
|||
: mQuotaMutex("QuotaManager.mQuotaMutex"),
|
||||
mTemporaryStorageLimit(0),
|
||||
mTemporaryStorageUsage(0),
|
||||
mNextDirectoryLockId(0),
|
||||
mTemporaryStorageInitialized(false),
|
||||
mCacheUsable(false) {
|
||||
AssertIsOnOwningThread();
|
||||
|
@ -3532,9 +3566,9 @@ auto QuotaManager::CreateDirectoryLock(
|
|||
MOZ_ASSERT_IF(!aInternal, aClientType.Value() < Client::TypeMax());
|
||||
MOZ_ASSERT_IF(!aInternal, aOpenListener);
|
||||
|
||||
RefPtr<DirectoryLockImpl> lock =
|
||||
new DirectoryLockImpl(this, aPersistenceType, aGroup, aOriginScope,
|
||||
aClientType, aExclusive, aInternal, aOpenListener);
|
||||
RefPtr<DirectoryLockImpl> lock = new DirectoryLockImpl(
|
||||
this, aPersistenceType, aGroup, aOriginScope, aClientType, aExclusive,
|
||||
aInternal, aOpenListener, GenerateDirectoryLockId());
|
||||
|
||||
mPendingDirectoryLocks.AppendElement(lock);
|
||||
|
||||
|
@ -3570,7 +3604,8 @@ auto QuotaManager::CreateDirectoryLockForEviction(
|
|||
this, Nullable<PersistenceType>(aPersistenceType), aGroup,
|
||||
OriginScope::FromOrigin(aOrigin), Nullable<Client::Type>(),
|
||||
/* aExclusive */ true,
|
||||
/* aInternal */ true, nullptr);
|
||||
/* aInternal */ true, nullptr, /* aDirectoryLockId */
|
||||
kBypassDirectoryLockIdTableId);
|
||||
|
||||
#ifdef DEBUG
|
||||
for (uint32_t index = mDirectoryLocks.Length(); index > 0; index--) {
|
||||
|
@ -3590,6 +3625,12 @@ void QuotaManager::RegisterDirectoryLock(DirectoryLockImpl* aLock) {
|
|||
|
||||
mDirectoryLocks.AppendElement(aLock);
|
||||
|
||||
if (aLock->ShouldUpdateLockIdTable()) {
|
||||
MutexAutoLock lock(mQuotaMutex);
|
||||
|
||||
mDirectoryLockIdTable.Put(aLock->GetId(), aLock);
|
||||
}
|
||||
|
||||
if (aLock->ShouldUpdateLockTable()) {
|
||||
const Nullable<PersistenceType>& persistenceType =
|
||||
aLock->GetPersistenceType();
|
||||
|
@ -3621,9 +3662,17 @@ void QuotaManager::RegisterDirectoryLock(DirectoryLockImpl* aLock) {
|
|||
|
||||
void QuotaManager::UnregisterDirectoryLock(DirectoryLockImpl* aLock) {
|
||||
AssertIsOnOwningThread();
|
||||
MOZ_ASSERT(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()) {
|
||||
const Nullable<PersistenceType>& persistenceType =
|
||||
aLock->GetPersistenceType();
|
||||
|
@ -4646,6 +4695,36 @@ already_AddRefed<QuotaObject> QuotaManager::GetQuotaObject(
|
|||
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,
|
||||
const nsACString& aOrigin) {
|
||||
AssertIsOnIOThread();
|
||||
|
@ -7600,6 +7679,22 @@ bool QuotaManager::IsSanitizedOriginValid(const nsACString& aSanitizedOrigin) {
|
|||
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
|
||||
******************************************************************************/
|
||||
|
|
|
@ -63,6 +63,10 @@ class DirectoryLock : public RefCountedObject {
|
|||
friend class DirectoryLockImpl;
|
||||
|
||||
public:
|
||||
const nsACString& GetOrigin() const;
|
||||
|
||||
int64_t GetId() const;
|
||||
|
||||
already_AddRefed<DirectoryLock> Specialize(PersistenceType aPersistenceType,
|
||||
const nsACString& aGroup,
|
||||
const nsACString& aOrigin,
|
||||
|
@ -232,6 +236,9 @@ class QuotaManager final : public BackgroundThreadObject {
|
|||
int64_t aFileSize = -1,
|
||||
int64_t* aFileSizeOut = nullptr);
|
||||
|
||||
already_AddRefed<QuotaObject> GetQuotaObject(const int64_t aDirectoryLockId,
|
||||
const nsAString& aPath);
|
||||
|
||||
Nullable<bool> OriginPersisted(const nsACString& aGroup,
|
||||
const nsACString& aOrigin);
|
||||
|
||||
|
@ -545,6 +552,8 @@ class QuotaManager final : public BackgroundThreadObject {
|
|||
|
||||
bool IsSanitizedOriginValid(const nsACString& aSanitizedOrigin);
|
||||
|
||||
int64_t GenerateDirectoryLockId();
|
||||
|
||||
static void ShutdownTimerCallback(nsITimer* aTimer, void* aClosure);
|
||||
|
||||
// Thread on which IO is performed.
|
||||
|
@ -562,9 +571,16 @@ class QuotaManager final : public BackgroundThreadObject {
|
|||
// Maintains a list of directory locks that are queued.
|
||||
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;
|
||||
|
||||
// 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.
|
||||
DirectoryLockTable mTemporaryDirectoryLockTable;
|
||||
DirectoryLockTable mDefaultDirectoryLockTable;
|
||||
|
@ -594,6 +610,7 @@ class QuotaManager final : public BackgroundThreadObject {
|
|||
|
||||
uint64_t mTemporaryStorageLimit;
|
||||
uint64_t mTemporaryStorageUsage;
|
||||
int64_t mNextDirectoryLockId;
|
||||
bool mTemporaryStorageInitialized;
|
||||
bool mCacheUsable;
|
||||
};
|
||||
|
|
|
@ -299,56 +299,21 @@ already_AddRefed<QuotaObject> GetQuotaObjectFromNameAndParameters(
|
|||
MOZ_ASSERT(zName);
|
||||
MOZ_ASSERT(zURIParameterKey);
|
||||
|
||||
const char* persistenceType =
|
||||
sqlite3_uri_parameter(zURIParameterKey, "persistenceType");
|
||||
if (!persistenceType) {
|
||||
const char* directoryLockIdParam =
|
||||
sqlite3_uri_parameter(zURIParameterKey, "directoryLockId");
|
||||
if (!directoryLockIdParam) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const char* group = sqlite3_uri_parameter(zURIParameterKey, "group");
|
||||
if (!group) {
|
||||
NS_WARNING("SQLite URI had 'persistenceType' but not 'group'?!");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
nsresult rv;
|
||||
const int64_t directoryLockId =
|
||||
nsDependentCString(directoryLockIdParam).ToInteger64(&rv);
|
||||
MOZ_RELEASE_ASSERT(NS_SUCCEEDED(rv));
|
||||
|
||||
QuotaManager* quotaManager = QuotaManager::Get();
|
||||
MOZ_ASSERT(quotaManager);
|
||||
|
||||
return quotaManager->GetQuotaObject(
|
||||
PersistenceTypeFromText(nsDependentCString(persistenceType)), escGroup,
|
||||
escOrigin, Client::TypeFromText(nsDependentCString(clientType)),
|
||||
return quotaManager->GetQuotaObject(directoryLockId,
|
||||
NS_ConvertUTF8toUTF16(zName));
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче