Bug 1547688 - LSNG: Preloading can use gUsages hash table to quickly finish if there's nothing to preload; r=asuth
authorJan Varga <jan.varga@gmail.com>
Mon, 29 Apr 2019 14:23:55 +0200
changeset 534718 248d2f08f8bd4524658e8840c0e496d82102a15e
parent 534717 7658320df0a9c4619fe5fa51f65080c8d72d7e51
child 534719 f3bff9237a3016bbf02ea5bb37601ba3e13f84b3
push id2082
push userffxbld-merge
push dateMon, 01 Jul 2019 08:34:18 +0000
treeherdermozilla-release@2fb19d0466d2 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersasuth
bugs1547688
milestone68.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1547688 - LSNG: Preloading can use gUsages hash table to quickly finish if there's nothing to preload; r=asuth Differential Revision: https://phabricator.services.mozilla.com/D29194
dom/cache/Context.cpp
dom/indexedDB/ActorsParent.cpp
dom/localstorage/ActorsParent.cpp
dom/quota/ActorsParent.cpp
dom/quota/QuotaManager.h
dom/simpledb/ActorsParent.cpp
--- a/dom/cache/Context.cpp
+++ b/dom/cache/Context.cpp
@@ -384,18 +384,17 @@ Context::QuotaInitRunnable::Run() {
         resolver->Resolve(NS_ERROR_ABORT);
         break;
       }
 
       QuotaManager* qm = QuotaManager::Get();
       MOZ_DIAGNOSTIC_ASSERT(qm);
       nsresult rv = qm->EnsureOriginIsInitialized(
           PERSISTENCE_TYPE_DEFAULT, mQuotaInfo.mSuffix, mQuotaInfo.mGroup,
-          mQuotaInfo.mOrigin,
-          /* aCreateIfNotExists */ true, getter_AddRefs(mQuotaInfo.mDir));
+          mQuotaInfo.mOrigin, getter_AddRefs(mQuotaInfo.mDir));
       if (NS_FAILED(rv)) {
         resolver->Resolve(rv);
         break;
       }
 
       mState = STATE_RUN_ON_TARGET;
 
       MOZ_ALWAYS_SUCCEEDS(mTarget->Dispatch(this, nsIThread::DISPATCH_NORMAL));
--- a/dom/indexedDB/ActorsParent.cpp
+++ b/dom/indexedDB/ActorsParent.cpp
@@ -17154,18 +17154,17 @@ nsresult Maintenance::DirectoryWork() {
             persistenceType, group, origin, std::move(databasePaths)));
 
         nsCOMPtr<nsIFile> directory;
 
         // Idle maintenance may occur before origin is initailized.
         // Ensure origin is initialized first. It will initialize all origins
         // for temporary storage including IDB origins.
         rv = quotaManager->EnsureOriginIsInitialized(
-            persistenceType, suffix, group, origin,
-            /* aCreateIfNotExists */ true, getter_AddRefs(directory));
+            persistenceType, suffix, group, origin, getter_AddRefs(directory));
 
         if (NS_WARN_IF(NS_FAILED(rv))) {
           return rv;
         }
       }
     }
   }
 
@@ -19864,18 +19863,17 @@ nsresult OpenDatabaseOp::DoDatabaseWork(
   PersistenceType persistenceType = mCommonParams.metadata().persistenceType();
 
   QuotaManager* quotaManager = QuotaManager::Get();
   MOZ_ASSERT(quotaManager);
 
   nsCOMPtr<nsIFile> dbDirectory;
 
   nsresult rv = quotaManager->EnsureOriginIsInitialized(
-      persistenceType, mSuffix, mGroup, mOrigin,
-      /* aCreateIfNotExists */ true, getter_AddRefs(dbDirectory));
+      persistenceType, mSuffix, mGroup, mOrigin, getter_AddRefs(dbDirectory));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   rv = dbDirectory->Append(NS_LITERAL_STRING(IDB_DIRECTORY_NAME));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
--- a/dom/localstorage/ActorsParent.cpp
+++ b/dom/localstorage/ActorsParent.cpp
@@ -2895,16 +2895,32 @@ void InitUsageForOrigin(const nsACString
   if (!gUsages) {
     gUsages = new UsageHashtable();
   }
 
   MOZ_ASSERT(!gUsages->Contains(aOrigin));
   gUsages->Put(aOrigin, aUsage);
 }
 
+bool GetUsageForOrigin(const nsACString& aOrigin, int64_t& aUsage) {
+  AssertIsOnIOThread();
+
+  if (gUsages) {
+    int64_t usage;
+    if (gUsages->Get(aOrigin, &usage)) {
+      MOZ_ASSERT(usage >= 0);
+
+      aUsage = usage;
+      return true;
+    }
+  }
+
+  return false;
+}
+
 void UpdateUsageForOrigin(const nsACString& aOrigin, int64_t aUsage) {
   AssertIsOnIOThread();
   MOZ_ASSERT(gUsages);
   MOZ_ASSERT(gUsages->Contains(aOrigin));
 
   gUsages->Put(aOrigin, aUsage);
 }
 
@@ -6689,39 +6705,56 @@ nsresult PrepareDatastoreOp::DatabaseWor
   if (NS_WARN_IF(QuotaClient::IsShuttingDownOnNonBackgroundThread()) ||
       !MayProceedOnNonOwningThread()) {
     return NS_ERROR_FAILURE;
   }
 
   QuotaManager* quotaManager = QuotaManager::Get();
   MOZ_ASSERT(quotaManager);
 
-  nsresult rv;
+  // This must be called before EnsureTemporaryStorageIsInitialized.
+  nsresult rv = quotaManager->EnsureStorageIsInitialized();
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+
+  // This ensures that gUsages gets populated with usages for existings origin
+  // directories.
+  rv = quotaManager->EnsureTemporaryStorageIsInitialized();
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
 
   if (!gArchivedOrigins) {
     rv = LoadArchivedOrigins();
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
     MOZ_ASSERT(gArchivedOrigins);
   }
 
   bool hasDataForMigration = mArchivedOriginScope->HasMatches(gArchivedOrigins);
 
+  // If there's nothing to preload (except the case when we want to migrate data
+  // during preloading), then we can finish the operation without creating a
+  // datastore in GetResponse (GetResponse won't create a datastore if
+  // mDatatabaseNotAvailable and mForPreload are both true).
+  int64_t usage;
+  if (mForPreload && !GetUsageForOrigin(mOrigin, usage) &&
+      !hasDataForMigration) {
+    return DatabaseNotAvailable();
+  }
+
   // Initialize the origin even when the origin directory doesn't exist and we
-  // don't have data for migration (except the case when we are just trying to
-  // preload data). GetQuotaObject in GetResponse would fail otherwise.
+  // don't have data for migration. GetQuotaObject in GetResponse would fail
+  // otherwise.
   nsCOMPtr<nsIFile> directoryEntry;
-  rv = quotaManager->EnsureOriginIsInitialized(
-      PERSISTENCE_TYPE_DEFAULT, mSuffix, mGroup, mOrigin,
-      /* aCreateIfNotExists */ !mForPreload || hasDataForMigration,
-      getter_AddRefs(directoryEntry));
-  if (rv == NS_ERROR_NOT_AVAILABLE) {
-    return DatabaseNotAvailable();
-  }
+  rv = quotaManager->EnsureOriginIsInitialized(PERSISTENCE_TYPE_DEFAULT,
+                                               mSuffix, mGroup, mOrigin,
+                                               getter_AddRefs(directoryEntry));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   rv = directoryEntry->Append(NS_LITERAL_STRING(LS_DIRECTORY_NAME));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
@@ -6732,28 +6765,17 @@ nsresult PrepareDatastoreOp::DatabaseWor
   }
 
   // The ls directory doesn't need to be created when we don't have data for
   // migration. It will be created on the connection thread in
   // Connection::EnsureStorageConnection.
   rv = EnsureDirectoryEntry(directoryEntry,
                             /* aCreateIfNotExists */ hasDataForMigration,
                             /* aIsDirectory */ true);
-  if (rv == NS_ERROR_NOT_AVAILABLE) {
-    if (mForPreload) {
-      // There's nothing to preload. Finish the operation without creating a
-      // datastore in GetResponse (GetResponse won't create a datastore if
-      // mDatatabaseNotAvailable and mForPreload are both true).
-      return DatabaseNotAvailable();
-    }
-
-    // Keep going if !mForPreload so that we will populate mDatabaseFilePath
-    // which is needed by GetQuotaObject. We will still return via call to
-    // DatabaseNotAvailable() below in the !alreadyExisted else branch.
-  } else if (NS_WARN_IF(NS_FAILED(rv))) {
+  if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   rv = directoryEntry->Append(NS_LITERAL_STRING(DATA_FILE_NAME));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
@@ -6764,39 +6786,32 @@ nsresult PrepareDatastoreOp::DatabaseWor
 
   // The database doesn't need to be created when we don't have data for
   // migration. It will be created on the connection thread in
   // Connection::EnsureStorageConnection.
   bool alreadyExisted;
   rv = EnsureDirectoryEntry(directoryEntry,
                             /* aCreateIfNotExists */ hasDataForMigration,
                             /* aIsDirectory */ false, &alreadyExisted);
-  if (rv == NS_ERROR_NOT_AVAILABLE) {
-    if (mForPreload) {
-      // There's nothing to preload, finish the operation without creating a
-      // datastore in GetResponse (GetResponse won't create a datastore if
-      // mDatatabaseNotAvailable and mForPreload are both true).
-      return DatabaseNotAvailable();
-    }
-  } else if (NS_WARN_IF(NS_FAILED(rv))) {
+  if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   if (alreadyExisted) {
     MOZ_ASSERT(gUsages);
     DebugOnly<bool> hasUsage = gUsages->Get(mOrigin, &mUsage);
     MOZ_ASSERT(hasUsage);
   } else {
-    MOZ_ASSERT(!mForPreload);
+    // The database doesn't exist.
 
     if (!hasDataForMigration) {
-      // The ls directory or database doesn't exist and we don't have data for
-      // migration. Finish the operation, but create an empty datastore in
-      // GetResponse (GetResponse will create an empty datastore if
-      // mDatabaseNotAvailable is true and mForPreload is false).
+      // The database doesn't exist and we don't have data for migration.
+      // Finish the operation, but create an empty datastore in GetResponse
+      // (GetResponse will create an empty datastore if mDatabaseNotAvailable
+      // is true and mForPreload is false).
       return DatabaseNotAvailable();
     }
 
     MOZ_ASSERT(mUsage == 0);
     InitUsageForOrigin(mOrigin, mUsage);
   }
 
   nsCOMPtr<nsIFile> usageFile;
@@ -6991,17 +7006,17 @@ nsresult PrepareDatastoreOp::EnsureDirec
     return rv;
   }
 
   if (!exists) {
     if (!aCreateIfNotExists) {
       if (aAlreadyExisted) {
         *aAlreadyExisted = false;
       }
-      return NS_ERROR_NOT_AVAILABLE;
+      return NS_OK;
     }
 
     if (aIsDirectory) {
       rv = aEntry->Create(nsIFile::DIRECTORY_TYPE, 0755);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
     }
@@ -8284,22 +8299,20 @@ nsresult QuotaClient::GetUsageForOrigin(
                                         UsageInfo* aUsageInfo) {
   AssertIsOnIOThread();
   MOZ_ASSERT(aPersistenceType == PERSISTENCE_TYPE_DEFAULT);
   MOZ_ASSERT(aUsageInfo);
 
   // We can't open the database at this point, since it can be already used
   // by the connection thread. Use the cached value instead.
 
-  if (gUsages) {
-    int64_t usage;
-    if (gUsages->Get(aOrigin, &usage)) {
-      MOZ_ASSERT(usage >= 0);
-      aUsageInfo->AppendToDatabaseUsage(usage);
-    }
+  int64_t usage;
+  if (mozilla::dom::GetUsageForOrigin(aOrigin, usage)) {
+    MOZ_ASSERT(usage >= 0);
+    aUsageInfo->AppendToDatabaseUsage(usage);
   }
 
   return NS_OK;
 }
 
 nsresult QuotaClient::AboutToClearOrigins(
     const Nullable<PersistenceType>& aPersistenceType,
     const OriginScope& aOriginScope) {
--- a/dom/quota/ActorsParent.cpp
+++ b/dom/quota/ActorsParent.cpp
@@ -5624,41 +5624,37 @@ void QuotaManager::OpenDirectoryInternal
         mClients[index]->AbortOperations(iter.Get()->GetKey());
       }
     }
   }
 }
 
 nsresult QuotaManager::EnsureOriginIsInitialized(
     PersistenceType aPersistenceType, const nsACString& aSuffix,
-    const nsACString& aGroup, const nsACString& aOrigin,
-    bool aCreateIfNotExists, nsIFile** aDirectory) {
+    const nsACString& aGroup, const nsACString& aOrigin, nsIFile** aDirectory) {
   AssertIsOnIOThread();
   MOZ_ASSERT(aDirectory);
 
   nsCOMPtr<nsIFile> directory;
   bool created;
   nsresult rv = EnsureOriginIsInitializedInternal(
-      aPersistenceType, aSuffix, aGroup, aOrigin, aCreateIfNotExists,
-      getter_AddRefs(directory), &created);
-  if (rv == NS_ERROR_NOT_AVAILABLE) {
-    return rv;
-  }
+      aPersistenceType, aSuffix, aGroup, aOrigin, getter_AddRefs(directory),
+      &created);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   directory.forget(aDirectory);
   return NS_OK;
 }
 
 nsresult QuotaManager::EnsureOriginIsInitializedInternal(
     PersistenceType aPersistenceType, const nsACString& aSuffix,
-    const nsACString& aGroup, const nsACString& aOrigin,
-    bool aCreateIfNotExists, nsIFile** aDirectory, bool* aCreated) {
+    const nsACString& aGroup, const nsACString& aOrigin, nsIFile** aDirectory,
+    bool* aCreated) {
   AssertIsOnIOThread();
   MOZ_ASSERT(aDirectory);
   MOZ_ASSERT(aCreated);
 
   nsresult rv = EnsureStorageIsInitialized();
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Get directory for this origin and persistence type.
@@ -5676,20 +5672,17 @@ nsresult QuotaManager::EnsureOriginIsIni
   } else {
     rv = EnsureTemporaryStorageIsInitialized();
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
   }
 
   bool created;
-  rv = EnsureOriginDirectory(directory, aCreateIfNotExists, &created);
-  if (rv == NS_ERROR_NOT_AVAILABLE) {
-    return rv;
-  }
+  rv = EnsureOriginDirectory(directory, &created);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   int64_t timestamp;
   if (aPersistenceType == PERSISTENCE_TYPE_PERSISTENT) {
     if (created) {
       rv = CreateDirectoryMetadataFiles(directory,
@@ -5798,33 +5791,28 @@ nsresult QuotaManager::EnsureTemporarySt
   mTemporaryStorageInitialized = true;
 
   CheckTemporaryStorageLimits();
 
   return rv;
 }
 
 nsresult QuotaManager::EnsureOriginDirectory(nsIFile* aDirectory,
-                                             bool aCreateIfNotExists,
                                              bool* aCreated) {
   AssertIsOnIOThread();
   MOZ_ASSERT(aDirectory);
   MOZ_ASSERT(aCreated);
 
   bool exists;
   nsresult rv = aDirectory->Exists(&exists);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   if (!exists) {
-    if (!aCreateIfNotExists) {
-      return NS_ERROR_NOT_AVAILABLE;
-    }
-
     nsString leafName;
     rv = aDirectory->GetLeafName(leafName);
     if (NS_WARN_IF(NS_FAILED(rv))) {
       return rv;
     }
 
     if (!IsSanitizedOriginValid(NS_ConvertUTF16toUTF8(leafName))) {
       QM_WARNING(
@@ -7921,17 +7909,17 @@ nsresult InitOriginOp::DoDirectoryWork(Q
   MOZ_ASSERT(!mPersistenceType.IsNull());
 
   AUTO_PROFILER_LABEL("InitOriginOp::DoDirectoryWork", OTHER);
 
   nsCOMPtr<nsIFile> directory;
   bool created;
   nsresult rv = aQuotaManager->EnsureOriginIsInitializedInternal(
       mPersistenceType.Value(), mSuffix, mGroup, mOriginScope.GetOrigin(),
-      /* aCreateIfNotExists */ true, getter_AddRefs(directory), &created);
+      getter_AddRefs(directory), &created);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   mCreated = created;
 
   return NS_OK;
 }
@@ -8434,19 +8422,17 @@ nsresult PersistOp::DoDirectoryWork(Quot
   nsresult rv = aQuotaManager->GetDirectoryForOrigin(mPersistenceType.Value(),
                                                      mOriginScope.GetOrigin(),
                                                      getter_AddRefs(directory));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   bool created;
-  rv = aQuotaManager->EnsureOriginDirectory(directory,
-                                            /* aCreateIfNotExists */ true,
-                                            &created);
+  rv = aQuotaManager->EnsureOriginDirectory(directory, &created);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   if (created) {
     int64_t timestamp;
     rv = CreateDirectoryMetadataFiles(directory,
                                       /* aPersisted */ true, mSuffix, mGroup,
--- a/dom/quota/QuotaManager.h
+++ b/dom/quota/QuotaManager.h
@@ -257,28 +257,28 @@ class QuotaManager final : public Backgr
 #endif
 
   nsresult EnsureStorageIsInitialized();
 
   nsresult EnsureOriginIsInitialized(PersistenceType aPersistenceType,
                                      const nsACString& aSuffix,
                                      const nsACString& aGroup,
                                      const nsACString& aOrigin,
-                                     bool aCreateIfNotExists,
                                      nsIFile** aDirectory);
 
-  nsresult EnsureOriginIsInitializedInternal(
-      PersistenceType aPersistenceType, const nsACString& aSuffix,
-      const nsACString& aGroup, const nsACString& aOrigin,
-      bool aCreateIfNotExists, nsIFile** aDirectory, bool* aCreated);
+  nsresult EnsureOriginIsInitializedInternal(PersistenceType aPersistenceType,
+                                             const nsACString& aSuffix,
+                                             const nsACString& aGroup,
+                                             const nsACString& aOrigin,
+                                             nsIFile** aDirectory,
+                                             bool* aCreated);
 
   nsresult EnsureTemporaryStorageIsInitialized();
 
-  nsresult EnsureOriginDirectory(nsIFile* aDirectory, bool aCreateIfNotExists,
-                                 bool* aCreated);
+  nsresult EnsureOriginDirectory(nsIFile* aDirectory, bool* aCreated);
 
   nsresult AboutToClearOrigins(
       const Nullable<PersistenceType>& aPersistenceType,
       const OriginScope& aOriginScope,
       const Nullable<Client::Type>& aClientType);
 
   void OriginClearCompleted(PersistenceType aPersistenceType,
                             const nsACString& aOrigin,
--- a/dom/simpledb/ActorsParent.cpp
+++ b/dom/simpledb/ActorsParent.cpp
@@ -1147,17 +1147,17 @@ nsresult OpenOp::DatabaseWork() {
   }
 
   QuotaManager* quotaManager = QuotaManager::Get();
   MOZ_ASSERT(quotaManager);
 
   nsCOMPtr<nsIFile> dbDirectory;
   nsresult rv = quotaManager->EnsureOriginIsInitialized(
       PERSISTENCE_TYPE_DEFAULT, mSuffix, mGroup, mOrigin,
-      /* aCreateIfNotExists */ true, getter_AddRefs(dbDirectory));
+      getter_AddRefs(dbDirectory));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   rv = dbDirectory->Append(NS_LITERAL_STRING(SDB_DIRECTORY_NAME));
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }