Bug 1638396 - Use Result in FileHelper::CreateFileFromStream. r=dom-workers-and-storage-reviewers,edenchuang
☠☠ backed out by 67622eb267b9 ☠ ☠
authorSimon Giesecke <sgiesecke@mozilla.com>
Wed, 01 Jul 2020 09:03:35 +0000
changeset 538179 bb01f404ab4728eee5b3bb11e1e8620025730462
parent 538178 b2142123046300857dc78bb694d5c7ce2a443604
child 538180 633bf93752dc38e9c22aefc1f0b74f749c90442d
push id120456
push usersgiesecke@mozilla.com
push dateWed, 01 Jul 2020 09:34:35 +0000
treeherderautoland@633bf93752dc [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdom-workers-and-storage-reviewers, edenchuang
bugs1638396
milestone80.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 1638396 - Use Result in FileHelper::CreateFileFromStream. r=dom-workers-and-storage-reviewers,edenchuang Differential Revision: https://phabricator.services.mozilla.com/D75584
dom/indexedDB/ActorsParent.cpp
--- a/dom/indexedDB/ActorsParent.cpp
+++ b/dom/indexedDB/ActorsParent.cpp
@@ -27353,113 +27353,108 @@ nsCOMPtr<nsIFile> FileHelper::GetFile(co
 }
 
 nsCOMPtr<nsIFile> FileHelper::GetJournalFile(const FileInfo& aFileInfo) {
   MOZ_ASSERT(!IsOnBackgroundThread());
 
   return mFileManager->GetFileForId(mJournalDirectory->get(), aFileInfo.Id());
 }
 
+static auto FailureIfFalse(const bool aArg)
+    -> Result<decltype(Ok()), nsresult> {
+  if (NS_WARN_IF(!aArg)) {
+    return Err(NS_ERROR_FAILURE);
+  }
+  return Ok();
+};
+
 nsresult FileHelper::CreateFileFromStream(nsIFile& aFile, nsIFile& aJournalFile,
                                           nsIInputStream& aInputStream,
                                           bool aCompress) {
   MOZ_ASSERT(!IsOnBackgroundThread());
 
-  bool exists;
-  nsresult rv = aFile.Exists(&exists);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
+  auto existsOrErr = ToResultInvoke(aFile, &nsIFile::Exists);
+  if (NS_WARN_IF(existsOrErr.isErr())) {
+    return existsOrErr.propagateErr();
   }
 
   // DOM blobs that are being stored in IDB are cached by calling
   // IDBDatabase::GetOrCreateFileActorForBlob. So if the same DOM blob is stored
   // again under a different key or in a different object store, we just add
   // a new reference instead of creating a new copy (all such stored blobs share
   // the same id).
   // However, it can happen that CreateFileFromStream failed due to quota
   // exceeded error and for some reason the orphaned file couldn't be deleted
   // immediately. Now, if the operation is being repeated, the DOM blob is
   // already cached, so it has the same file id which clashes with the orphaned
   // file. We could do some tricks to restore previous copy loop, but it's safer
   // to just delete the orphaned file and start from scratch.
   // This corner case is partially simulated in test_file_copy_failure.js
-  if (exists) {
-    bool isFile;
-    rv = aFile.IsFile(&isFile);
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
-    }
-
-    if (NS_WARN_IF(!isFile)) {
-      return NS_ERROR_FAILURE;
-    }
-
-    rv = aJournalFile.Exists(&exists);
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
-    }
-
-    if (NS_WARN_IF(!exists)) {
-      return NS_ERROR_FAILURE;
-    }
-
-    rv = aJournalFile.IsFile(&isFile);
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
-    }
-
-    if (NS_WARN_IF(!isFile)) {
-      return NS_ERROR_FAILURE;
-    }
-
-    IDB_WARNING("Deleting orphaned file!");
-
-    rv = mFileManager->SyncDeleteFile(aFile, aJournalFile);
-    if (NS_WARN_IF(NS_FAILED(rv))) {
-      return rv;
+  if (existsOrErr.inspect()) {
+    auto res = ToResultInvoke(aFile, &nsIFile::IsFile)
+                   .andThen(FailureIfFalse)
+                   .andThen([&aJournalFile](auto) {
+                     return ToResultInvoke(aJournalFile, &nsIFile::Exists);
+                   })
+                   .andThen(FailureIfFalse)
+                   .andThen([&aJournalFile](auto) {
+                     return ToResultInvoke(aJournalFile, &nsIFile::IsFile);
+                   })
+                   .andThen(FailureIfFalse)
+                   .andThen([this, &aFile, &aJournalFile](auto) {
+                     IDB_WARNING("Deleting orphaned file!");
+
+                     return ToResult(
+                         mFileManager->SyncDeleteFile(aFile, aJournalFile));
+                   });
+
+    if (res.isErr()) {
+      return res.unwrapErr();
     }
   }
 
   // Create a journal file first.
-  rv = aJournalFile.Create(nsIFile::NORMAL_FILE_TYPE, 0644);
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
-  }
-
-  // Now try to copy the stream.
-  RefPtr<FileOutputStream> fileOutputStream =
-      CreateFileOutputStream(mFileManager->Type(), mFileManager->Group(),
-                             mFileManager->Origin(), Client::IDB, &aFile);
-  if (NS_WARN_IF(!fileOutputStream)) {
-    return NS_ERROR_FAILURE;
-  }
-
-  AutoTArray<char, kFileCopyBufferSize> buffer;
-  const auto actualOutputStream =
-      [aCompress, &buffer, &fileOutputStream]() -> nsCOMPtr<nsIOutputStream> {
-    if (aCompress) {
-      auto snappyOutputStream =
-          MakeRefPtr<SnappyCompressOutputStream>(fileOutputStream);
-
-      buffer.SetLength(snappyOutputStream->BlockSize());
-
-      return snappyOutputStream;
-    }
-
-    buffer.SetLength(kFileCopyBufferSize);
-    return std::move(fileOutputStream);
-  }();
-
-  rv = SyncCopy(aInputStream, *actualOutputStream, buffer.Elements(),
-                buffer.Length());
-  if (NS_WARN_IF(NS_FAILED(rv))) {
-    return rv;
-  }
-
-  return NS_OK;
+  auto res =
+      ToResult(aJournalFile.Create(nsIFile::NORMAL_FILE_TYPE, 0644))
+          .andThen([this, &aFile](
+                       auto) -> Result<nsCOMPtr<nsIOutputStream>, nsresult> {
+            // Now try to copy the stream.
+            nsCOMPtr<nsIOutputStream> fileOutputStream = CreateFileOutputStream(
+                mFileManager->Type(), mFileManager->Group(),
+                mFileManager->Origin(), Client::IDB, &aFile);
+            if (NS_WARN_IF(!fileOutputStream)) {
+              return Err(NS_ERROR_FAILURE);
+            }
+            return std::move(fileOutputStream);
+          })
+          .andThen([this, aCompress,
+                    &aInputStream](nsCOMPtr<nsIOutputStream> fileOutputStream) {
+            AutoTArray<char, kFileCopyBufferSize> buffer;
+            const auto actualOutputStream =
+                [aCompress, &buffer,
+                 fileOutputStream = std::move(
+                     fileOutputStream)]() mutable -> nsCOMPtr<nsIOutputStream> {
+              if (aCompress) {
+                auto snappyOutputStream =
+                    MakeRefPtr<SnappyCompressOutputStream>(fileOutputStream);
+
+                buffer.SetLength(snappyOutputStream->BlockSize());
+
+                return snappyOutputStream;
+              }
+
+              buffer.SetLength(kFileCopyBufferSize);
+              return std::move(fileOutputStream);
+            }();
+
+            return ToResult(SyncCopy(aInputStream, *actualOutputStream,
+                                     buffer.Elements(), buffer.Length()));
+          });
+
+  return res.isErr() ? res.unwrapErr() : NS_OK;
 }
 
 class FileHelper::ReadCallback final : public nsIInputStreamCallback {
  public:
   NS_DECL_THREADSAFE_ISUPPORTS
 
   ReadCallback()
       : mMutex("ReadCallback::mMutex"),