Bug 1168606 - Add support for preloading key-only cursors. r=ttung,asuth
☠☠ backed out by 2172f9a7aaf0 ☠ ☠
authorSimon Giesecke <sgiesecke@mozilla.com>
Tue, 05 Nov 2019 12:46:16 +0000
changeset 500607 6818224b9b119944f818554e4071a566bca4ed63
parent 500606 f1be81af7d6b1dd98040b90ff4e094da950f01f6
child 500608 96cb7140a4f6c3f9651944c824f35e73d5cff735
push id114166
push userapavel@mozilla.com
push dateThu, 07 Nov 2019 10:04:01 +0000
treeherdermozilla-inbound@d271c572a9bc [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersttung, asuth
bugs1168606
milestone72.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 1168606 - Add support for preloading key-only cursors. r=ttung,asuth Differential Revision: https://phabricator.services.mozilla.com/D44009
dom/indexedDB/ActorsChild.cpp
dom/indexedDB/ActorsChild.h
dom/indexedDB/ActorsParent.cpp
dom/indexedDB/PBackgroundIDBCursor.ipdl
--- a/dom/indexedDB/ActorsChild.cpp
+++ b/dom/indexedDB/ActorsChild.cpp
@@ -3222,16 +3222,26 @@ BackgroundCursorChild::CachedResponse::C
 BackgroundCursorChild::CachedResponse::CachedResponse(
     Key aKey, Key aLocaleAwareKey, Key aObjectStoreKey,
     StructuredCloneReadInfo&& aCloneInfo)
     : mKey{std::move(aKey)},
       mLocaleAwareKey{std::move(aLocaleAwareKey)},
       mObjectStoreKey{std::move(aObjectStoreKey)},
       mCloneInfo{std::move(aCloneInfo)} {}
 
+BackgroundCursorChild::CachedResponse::CachedResponse(Key aKey)
+    : mKey{std::move(aKey)} {}
+
+BackgroundCursorChild::CachedResponse::CachedResponse(Key aKey,
+                                                      Key aLocaleAwareKey,
+                                                      Key aObjectStoreKey)
+    : mKey{std::move(aKey)},
+      mLocaleAwareKey{std::move(aLocaleAwareKey)},
+      mObjectStoreKey{std::move(aObjectStoreKey)} {}
+
 // Does not need to be threadsafe since this only runs on one thread, but
 // inheriting from CancelableRunnable is easy.
 class BackgroundCursorChild::DelayedActionRunnable final
     : public CancelableRunnable {
   using ActionFunc = void (BackgroundCursorChild::*)();
 
   BackgroundCursorChild* mActor;
   RefPtr<IDBRequest> mRequest;
@@ -3428,35 +3438,38 @@ void BackgroundCursorChild::SendContinue
 }
 
 void BackgroundCursorChild::CompleteContinueRequestFromCache() {
   AssertIsOnOwningThread();
   MOZ_ASSERT(mTransaction);
   MOZ_ASSERT(mCursor);
   MOZ_ASSERT(mStrongCursor);
   MOZ_ASSERT(!mDelayedResponses.empty());
-  // TODO: Also support the other types.
-  MOZ_ASSERT(mCursor->GetType() == IDBCursor::Type_ObjectStore ||
-             mCursor->GetType() == IDBCursor::Type_Index);
 
   RefPtr<IDBCursor> cursor;
   mStrongCursor.swap(cursor);
 
   auto& item = mDelayedResponses.front();
   switch (mCursor->GetType()) {
     case IDBCursor::Type_ObjectStore:
       mCursor->Reset(std::move(item.mKey), std::move(item.mCloneInfo));
       break;
     case IDBCursor::Type_Index:
       mCursor->Reset(std::move(item.mKey), std::move(item.mLocaleAwareKey),
                      std::move(item.mObjectStoreKey),
                      std::move(item.mCloneInfo));
       break;
+    case IDBCursor::Type_ObjectStoreKey:
+      mCursor->Reset(std::move(item.mKey));
+      break;
+    case IDBCursor::Type_IndexKey:
+      mCursor->Reset(std::move(item.mKey), std::move(item.mLocaleAwareKey),
+                     std::move(item.mObjectStoreKey));
+      break;
     default:
-      // TODO: Also support the other types.
       MOZ_CRASH("Should never get here.");
   }
   mDelayedResponses.pop_front();
 
   IDB_LOG_MARK_CHILD_TRANSACTION_REQUEST(
       "PRELOAD: Consumed 1 cached response, %zu cached responses remaining",
       "Consumed cached response", mTransaction->LoggingSerialNumber(),
       mRequest->LoggingSerialNumber(),
@@ -3624,38 +3637,35 @@ void BackgroundCursorChild::HandleRespon
           newCursor = IDBCursor::Create(this, std::move(response.key()),
                                         std::move(cloneReadInfo));
           mCursor = newCursor;
         }
       });
 }
 
 void BackgroundCursorChild::HandleResponse(
-    const ObjectStoreKeyCursorResponse& aResponse) {
+    const nsTArray<ObjectStoreKeyCursorResponse>& aResponses) {
   AssertIsOnOwningThread();
-  MOZ_ASSERT(mRequest);
-  MOZ_ASSERT(mTransaction);
   MOZ_ASSERT(mObjectStore);
-  MOZ_ASSERT(!mStrongRequest);
-  MOZ_ASSERT(!mStrongCursor);
-
-  // XXX Fix this somehow...
-  auto& response = const_cast<ObjectStoreKeyCursorResponse&>(aResponse);
-
-  RefPtr<IDBCursor> newCursor;
-
-  if (mCursor) {
-    mCursor->Reset(std::move(response.key()));
-  } else {
-    newCursor = IDBCursor::Create(this, std::move(response.key()));
-    mCursor = newCursor;
-  }
-
-  ResultHelper helper(mRequest, mTransaction, mCursor);
-  DispatchSuccessEvent(&helper);
+
+  HandleMultipleCursorResponses(
+      aResponses, [this](ObjectStoreKeyCursorResponse& response) {
+        RefPtr<IDBCursor> newCursor;
+
+        if (mCursor) {
+          if (mCursor->IsContinueCalled()) {
+            mCursor->Reset(std::move(response.key()));
+          } else {
+            mCachedResponses.emplace_back(std::move(response.key()));
+          }
+        } else {
+          newCursor = IDBCursor::Create(this, std::move(response.key()));
+          mCursor = newCursor;
+        }
+      });
 }
 
 void BackgroundCursorChild::HandleResponse(
     const nsTArray<IndexCursorResponse>& aResponses) {
   AssertIsOnOwningThread();
   MOZ_ASSERT(mIndex);
 
   HandleMultipleCursorResponses(aResponses, [this](
@@ -3683,41 +3693,41 @@ void BackgroundCursorChild::HandleRespon
           this, std::move(response.key()), std::move(response.sortKey()),
           std::move(response.objectKey()), std::move(cloneReadInfo));
       mCursor = newCursor;
     }
   });
 }
 
 void BackgroundCursorChild::HandleResponse(
-    const IndexKeyCursorResponse& aResponse) {
+    const nsTArray<IndexKeyCursorResponse>& aResponses) {
   AssertIsOnOwningThread();
-  MOZ_ASSERT(mRequest);
-  MOZ_ASSERT(mTransaction);
   MOZ_ASSERT(mIndex);
-  MOZ_ASSERT(!mStrongRequest);
-  MOZ_ASSERT(!mStrongCursor);
-
-  // XXX Fix this somehow...
-  auto& response = const_cast<IndexKeyCursorResponse&>(aResponse);
-
-  RefPtr<IDBCursor> newCursor;
-
-  if (mCursor) {
-    mCursor->Reset(std::move(response.key()), std::move(response.sortKey()),
-                   std::move(response.objectKey()));
-  } else {
-    newCursor = IDBCursor::Create(this, std::move(response.key()),
-                                  std::move(response.sortKey()),
-                                  std::move(response.objectKey()));
-    mCursor = newCursor;
-  }
-
-  ResultHelper helper(mRequest, mTransaction, mCursor);
-  DispatchSuccessEvent(&helper);
+
+  HandleMultipleCursorResponses(
+      aResponses, [this](IndexKeyCursorResponse& response) {
+        RefPtr<IDBCursor> newCursor;
+
+        if (mCursor) {
+          if (mCursor->IsContinueCalled()) {
+            mCursor->Reset(std::move(response.key()),
+                           std::move(response.sortKey()),
+                           std::move(response.objectKey()));
+          } else {
+            mCachedResponses.emplace_back(std::move(response.key()),
+                                          std::move(response.sortKey()),
+                                          std::move(response.objectKey()));
+          }
+        } else {
+          newCursor = IDBCursor::Create(this, std::move(response.key()),
+                                        std::move(response.sortKey()),
+                                        std::move(response.objectKey()));
+          mCursor = newCursor;
+        }
+      });
 }
 
 void BackgroundCursorChild::ActorDestroy(ActorDestroyReason aWhy) {
   AssertIsOnOwningThread();
   MOZ_ASSERT_IF(aWhy == Deletion, !mStrongRequest);
   MOZ_ASSERT_IF(aWhy == Deletion, !mStrongCursor);
 
   MaybeCollectGarbageOnIPCMessage();
@@ -3769,26 +3779,26 @@ mozilla::ipc::IPCResult BackgroundCursor
     case CursorResponse::Tvoid_t:
       HandleResponse(aResponse.get_void_t());
       break;
 
     case CursorResponse::TArrayOfObjectStoreCursorResponse:
       HandleResponse(aResponse.get_ArrayOfObjectStoreCursorResponse());
       break;
 
-    case CursorResponse::TObjectStoreKeyCursorResponse:
-      HandleResponse(aResponse.get_ObjectStoreKeyCursorResponse());
+    case CursorResponse::TArrayOfObjectStoreKeyCursorResponse:
+      HandleResponse(aResponse.get_ArrayOfObjectStoreKeyCursorResponse());
       break;
 
     case CursorResponse::TArrayOfIndexCursorResponse:
       HandleResponse(aResponse.get_ArrayOfIndexCursorResponse());
       break;
 
-    case CursorResponse::TIndexKeyCursorResponse:
-      HandleResponse(aResponse.get_IndexKeyCursorResponse());
+    case CursorResponse::TArrayOfIndexKeyCursorResponse:
+      HandleResponse(aResponse.get_ArrayOfIndexKeyCursorResponse());
       break;
 
     default:
       MOZ_CRASH("Should never get here!");
   }
 
   transaction->OnRequestFinished(/* aRequestCompletedSuccessfully */ true);
 
--- a/dom/indexedDB/ActorsChild.h
+++ b/dom/indexedDB/ActorsChild.h
@@ -628,16 +628,18 @@ class BackgroundCursorChild final : publ
   class DelayedActionRunnable;
 
   struct CachedResponse {
     CachedResponse() = delete;
 
     CachedResponse(Key aKey, StructuredCloneReadInfo&& aCloneInfo);
     CachedResponse(Key aKey, Key aLocaleAwareKey, Key aObjectStoreKey,
                    StructuredCloneReadInfo&& aCloneInfo);
+    explicit CachedResponse(Key aKey);
+    CachedResponse(Key aKey, Key aLocaleAwareKey, Key aObjectStoreKey);
 
     CachedResponse(CachedResponse&& aOther) = default;
     CachedResponse& operator=(CachedResponse&& aOther) = default;
     CachedResponse(const CachedResponse& aOther) = delete;
     CachedResponse& operator=(const CachedResponse& aOther) = delete;
 
     Key mKey;
     Key mLocaleAwareKey;
@@ -712,28 +714,28 @@ class BackgroundCursorChild final : publ
   void CompleteContinueRequestFromCache();
 
   void HandleResponse(nsresult aResponse);
 
   void HandleResponse(const void_t& aResponse);
 
   void HandleResponse(const nsTArray<ObjectStoreCursorResponse>& aResponses);
 
-  void HandleResponse(const ObjectStoreKeyCursorResponse& aResponse);
+  void HandleResponse(const nsTArray<ObjectStoreKeyCursorResponse>& aResponses);
 
   void HandleResponse(const nsTArray<IndexCursorResponse>& aResponses);
 
   StructuredCloneReadInfo PrepareCloneReadInfo(
       SerializedStructuredCloneReadInfo&& aCloneInfo) const;
 
   template <typename T, typename Func>
   void HandleMultipleCursorResponses(const nsTArray<T>& aResponses,
                                      const Func& aHandleRecord);
 
-  void HandleResponse(const IndexKeyCursorResponse& aResponse);
+  void HandleResponse(const nsTArray<IndexKeyCursorResponse>& aResponses);
 
   // IPDL methods are only called by IPDL.
   virtual void ActorDestroy(ActorDestroyReason aWhy) override;
 
   virtual mozilla::ipc::IPCResult RecvResponse(
       const CursorResponse& aResponse) override;
 
  public:
--- a/dom/indexedDB/ActorsParent.cpp
+++ b/dom/indexedDB/ActorsParent.cpp
@@ -15212,18 +15212,19 @@ void Cursor::SendResponseInternal(
                 mPosition.IsUnset());
   MOZ_ASSERT_IF(aResponse.type() == CursorResponse::Tvoid_t,
                 mLocaleAwareRangeBound.IsUnset());
   MOZ_ASSERT_IF(aResponse.type() == CursorResponse::Tvoid_t,
                 mObjectStorePosition.IsUnset());
   MOZ_ASSERT_IF(
       aResponse.type() == CursorResponse::Tnsresult ||
           aResponse.type() == CursorResponse::Tvoid_t ||
-          aResponse.type() == CursorResponse::TObjectStoreKeyCursorResponse ||
-          aResponse.type() == CursorResponse::TIndexKeyCursorResponse,
+          aResponse.type() ==
+              CursorResponse::TArrayOfObjectStoreKeyCursorResponse ||
+          aResponse.type() == CursorResponse::TArrayOfIndexKeyCursorResponse,
       aFiles.IsEmpty());
   MOZ_ASSERT(!mActorDestroyed);
   MOZ_ASSERT(mCurrentlyRunningOp);
 
   for (size_t i = 0; i < aFiles.Length(); ++i) {
     const auto& files = aFiles[i];
     if (!files.IsEmpty()) {
       MOZ_ASSERT(aResponse.type() ==
@@ -25724,17 +25725,22 @@ void Cursor::CursorOpBase::Cleanup() {
   TransactionDatabaseOperationBase::Cleanup();
 }
 
 nsresult Cursor::CursorOpBase::PopulateResponseFromStatement(
     mozIStorageStatement* const aStmt, const bool aInitializeResponse) {
   Transaction()->AssertIsOnConnectionThread();
   MOZ_ASSERT(aInitializeResponse ==
              (mResponse.type() == CursorResponse::T__None));
-  MOZ_ASSERT_IF(mFiles.IsEmpty(), aInitializeResponse);
+  MOZ_ASSERT_IF(
+      mFiles.IsEmpty() &&
+          (mResponse.type() ==
+               CursorResponse::TArrayOfObjectStoreCursorResponse ||
+           mResponse.type() == CursorResponse::TArrayOfIndexCursorResponse),
+      aInitializeResponse);
 
   nsresult rv = mCursor->mPosition.SetFromStatement(aStmt, 0);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   IDB_LOG_MARK_PARENT_TRANSACTION_REQUEST(
       "PRELOAD: Populating response with key %s", "Populating",
@@ -25769,18 +25775,26 @@ nsresult Cursor::CursorOpBase::PopulateR
       response.cloneInfo().data().data = std::move(cloneInfo.mData);
       response.key() = mCursor->mPosition;
 
       mFiles.AppendElement(std::move(cloneInfo.mFiles));
       break;
     }
 
     case OpenCursorParams::TObjectStoreOpenKeyCursorParams: {
-      MOZ_ASSERT(aInitializeResponse);
-      mResponse = ObjectStoreKeyCursorResponse(mCursor->mPosition);
+      if (aInitializeResponse) {
+        mResponse = nsTArray<ObjectStoreKeyCursorResponse>();
+      } else {
+        MOZ_ASSERT(mResponse.type() ==
+                   CursorResponse::TArrayOfObjectStoreKeyCursorResponse);
+      }
+
+      auto& responses = mResponse.get_ArrayOfObjectStoreKeyCursorResponse();
+      auto& response = *responses.AppendElement();
+      response.key() = mCursor->mPosition;
       break;
     }
 
     case OpenCursorParams::TIndexOpenCursorParams: {
       rv = mCursor->mLocaleAwarePosition.SetFromStatement(aStmt, 1);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
@@ -25827,43 +25841,43 @@ nsresult Cursor::CursorOpBase::PopulateR
         return rv;
       }
 
       rv = mCursor->mObjectStorePosition.SetFromStatement(aStmt, 2);
       if (NS_WARN_IF(NS_FAILED(rv))) {
         return rv;
       }
 
-      MOZ_ASSERT(aInitializeResponse);
-      mResponse = IndexKeyCursorResponse(mCursor->mPosition,
-                                         mCursor->mLocaleAwarePosition,
-                                         mCursor->mObjectStorePosition);
+      if (aInitializeResponse) {
+        mResponse = nsTArray<IndexKeyCursorResponse>();
+      } else {
+        MOZ_ASSERT(mResponse.type() ==
+                   CursorResponse::TArrayOfIndexKeyCursorResponse);
+      }
+
+      auto& responses = mResponse.get_ArrayOfIndexKeyCursorResponse();
+      auto& response = *responses.AppendElement();
+      response.key() = mCursor->mPosition;
+      response.sortKey() = mCursor->mLocaleAwarePosition;
+      response.objectKey() = mCursor->mObjectStorePosition;
       break;
     }
 
     default:
       MOZ_CRASH("Should never get here!");
   }
 
   return NS_OK;
 }
 
 nsresult Cursor::CursorOpBase::PopulateExtraResponses(
     mozIStorageStatement* const aStmt, const uint32_t aMaxExtraCount,
     const nsCString& aOperation) {
   AssertIsOnConnectionThread();
 
-  if (mCursor->mType != OpenCursorParams::TObjectStoreOpenCursorParams &&
-      mCursor->mType != OpenCursorParams::TIndexOpenCursorParams) {
-    IDB_WARNING(
-        "PRELOAD: Not yet implemented. Extra results were queried, but are "
-        "discarded for now.");
-    return NS_OK;
-  }
-
   // For unique cursors, we need to skip records with the same key. The SQL
   // queries currently do not filter these out.
   Key previousKey =
       IsUnique(mCursor->mDirection)
           ? (mCursor->IsLocaleAware() ? mCursor->mLocaleAwarePosition
                                       : mCursor->mPosition)
           : Key{};
 
--- a/dom/indexedDB/PBackgroundIDBCursor.ipdl
+++ b/dom/indexedDB/PBackgroundIDBCursor.ipdl
@@ -74,19 +74,19 @@ struct IndexKeyCursorResponse
 };
 
 // TODO: All cursor responses must be arrays!
 union CursorResponse
 {
   void_t;
   nsresult;
   ObjectStoreCursorResponse[];
-  ObjectStoreKeyCursorResponse;
+  ObjectStoreKeyCursorResponse[];
   IndexCursorResponse[];
-  IndexKeyCursorResponse;
+  IndexKeyCursorResponse[];
 };
 
 protocol PBackgroundIDBCursor
 {
   manager PBackgroundIDBTransaction or PBackgroundIDBVersionChangeTransaction;
 
 parent:
   async DeleteMe();