Bug 1594892 - xpidl [array] removal from nsIMsgDatabase.refreshCache(). r=mkmelin
authorBen Campbell <benc@thunderbird.net>
Thu, 19 Dec 2019 14:14:00 +0200
changeset 37785 e68e4b9259f3dbd6e8015024673b4d7e74d9849f
parent 37784 fb1646d8e45c239e5e94bd3fbdbef16e2650f8f2
child 37786 1be1e6dac3864d2aa8f09065017b60233e0bd6cd
push id397
push userclokep@gmail.com
push dateMon, 10 Feb 2020 21:16:13 +0000
reviewersmkmelin
bugs1594892
Bug 1594892 - xpidl [array] removal from nsIMsgDatabase.refreshCache(). r=mkmelin
mailnews/base/src/nsMsgQuickSearchDBView.cpp
mailnews/base/src/nsMsgXFVirtualFolderDBView.cpp
mailnews/base/src/nsMsgXFVirtualFolderDBView.h
mailnews/db/msgdb/public/nsIMsgDatabase.idl
mailnews/db/msgdb/src/nsMsgDatabase.cpp
--- a/mailnews/base/src/nsMsgQuickSearchDBView.cpp
+++ b/mailnews/base/src/nsMsgQuickSearchDBView.cpp
@@ -302,30 +302,25 @@ nsMsgQuickSearchDBView::OnSearchDone(nsr
     uint32_t count = m_hdrHits.Count();
     // Build up message keys. The hits are in descending order but the cache
     // expects them to be in ascending key order.
     for (uint32_t i = count; i > 0; i--) {
       nsMsgKey key;
       m_hdrHits[i - 1]->GetMessageKey(&key);
       keyArray.AppendElement(key);
     }
-    nsMsgKey *staleHits;
-    uint32_t numBadHits;
     if (m_db) {
-      nsresult rv =
-          m_db->RefreshCache(searchUri.get(), m_hdrHits.Count(),
-                             keyArray.Elements(), &numBadHits, &staleHits);
+      nsTArray<nsMsgKey> staleHits;
+      nsresult rv = m_db->RefreshCache(searchUri.get(), keyArray, staleHits);
       NS_ENSURE_SUCCESS(rv, rv);
-      nsCOMPtr<nsIMsgDBHdr> hdrDeleted;
-
-      for (uint32_t i = 0; i < numBadHits; i++) {
-        m_db->GetMsgHdrForKey(staleHits[i], getter_AddRefs(hdrDeleted));
+      for (nsMsgKey staleKey : staleHits) {
+        nsCOMPtr<nsIMsgDBHdr> hdrDeleted;
+        m_db->GetMsgHdrForKey(staleKey, getter_AddRefs(hdrDeleted));
         if (hdrDeleted) OnHdrDeleted(hdrDeleted, nsMsgKey_None, 0, this);
       }
-      delete[] staleHits;
     }
     nsCOMPtr<nsIMsgDatabase> virtDatabase;
     nsCOMPtr<nsIDBFolderInfo> dbFolderInfo;
     nsresult rv = m_viewFolder->GetDBFolderInfoAndDB(
         getter_AddRefs(dbFolderInfo), getter_AddRefs(virtDatabase));
     NS_ENSURE_SUCCESS(rv, rv);
     uint32_t numUnread = 0;
     size_t numTotal = m_origKeys.Length();
--- a/mailnews/base/src/nsMsgXFVirtualFolderDBView.cpp
+++ b/mailnews/base/src/nsMsgXFVirtualFolderDBView.cpp
@@ -177,68 +177,64 @@ nsMsgXFVirtualFolderDBView::OnHdrPropert
     RemoveByIndex(index);
   else
     NoteChange(index, 1, nsMsgViewNotificationCode::changed);
 
   return NS_OK;
 }
 
 void nsMsgXFVirtualFolderDBView::UpdateCacheAndViewForFolder(
-    nsIMsgFolder *folder, nsMsgKey *newHits, uint32_t numNewHits) {
+    nsIMsgFolder *folder, nsTArray<nsMsgKey> const &newHits) {
   nsCOMPtr<nsIMsgDatabase> db;
   nsresult rv = folder->GetMsgDatabase(getter_AddRefs(db));
   if (NS_SUCCEEDED(rv) && db) {
     nsCString searchUri;
     m_viewFolder->GetURI(searchUri);
-    uint32_t numBadHits;
-    nsMsgKey *badHits;
-    rv = db->RefreshCache(searchUri.get(), numNewHits, newHits, &numBadHits,
-                          &badHits);
+    nsTArray<nsMsgKey> badHits;
+    rv = db->RefreshCache(searchUri.get(), newHits, badHits);
     if (NS_SUCCEEDED(rv)) {
       nsCOMPtr<nsIMsgDBHdr> badHdr;
-      for (uint32_t badHitIndex = 0; badHitIndex < numBadHits; badHitIndex++) {
+      for (nsMsgKey badKey : badHits) {
         // ### of course, this isn't quite right, since we should be
         // using FindHdr, and we shouldn't be expanding the threads.
-        db->GetMsgHdrForKey(badHits[badHitIndex], getter_AddRefs(badHdr));
+        db->GetMsgHdrForKey(badKey, getter_AddRefs(badHdr));
         // Let nsMsgSearchDBView decide what to do about this header
         // getting removed.
         if (badHdr) OnHdrDeleted(badHdr, nsMsgKey_None, 0, this);
       }
-
-      delete[] badHits;
     }
   }
 }
 
 void nsMsgXFVirtualFolderDBView::UpdateCacheAndViewForPrevSearchedFolders(
     nsIMsgFolder *curSearchFolder) {
   // Handle the most recent folder with hits, if any.
   if (m_curFolderGettingHits) {
     uint32_t count = m_hdrHits.Count();
     nsTArray<nsMsgKey> newHits;
     newHits.SetLength(count);
     for (uint32_t i = 0; i < count; i++)
       m_hdrHits[i]->GetMessageKey(&newHits[i]);
 
     newHits.Sort();
-    UpdateCacheAndViewForFolder(m_curFolderGettingHits, newHits.Elements(),
-                                newHits.Length());
+    UpdateCacheAndViewForFolder(m_curFolderGettingHits, newHits);
     m_foldersSearchingOver.RemoveObject(m_curFolderGettingHits);
   }
 
   while (m_foldersSearchingOver.Count() > 0) {
     // This new folder has cached hits.
     if (m_foldersSearchingOver[0] == curSearchFolder) {
       m_curFolderHasCachedHits = true;
       m_foldersSearchingOver.RemoveObjectAt(0);
       break;
     } else {
       // This must be a folder that had no hits with the current search.
       // So all cached hits, if any, need to be removed.
-      UpdateCacheAndViewForFolder(m_foldersSearchingOver[0], nullptr, 0);
+      nsTArray<nsMsgKey> noHits;
+      UpdateCacheAndViewForFolder(m_foldersSearchingOver[0], noHits);
       m_foldersSearchingOver.RemoveObjectAt(0);
     }
   }
 }
 NS_IMETHODIMP
 nsMsgXFVirtualFolderDBView::OnSearchHit(nsIMsgDBHdr *aMsgHdr,
                                         nsIMsgFolder *aFolder) {
   NS_ENSURE_ARG(aMsgHdr);
--- a/mailnews/base/src/nsMsgXFVirtualFolderDBView.h
+++ b/mailnews/base/src/nsMsgXFVirtualFolderDBView.h
@@ -43,18 +43,18 @@ class nsMsgXFVirtualFolderDBView : publi
   NS_IMETHOD OnHdrPropertyChanged(nsIMsgDBHdr *aHdrToChange, bool aPreChange,
                                   uint32_t *aStatus,
                                   nsIDBChangeListener *aInstigator) override;
   NS_IMETHOD GetMsgFolder(nsIMsgFolder **aMsgFolder) override;
 
   virtual nsresult OnNewHeader(nsIMsgDBHdr *newHdr, nsMsgKey parentKey,
                                bool ensureListed) override;
   void UpdateCacheAndViewForPrevSearchedFolders(nsIMsgFolder *curSearchFolder);
-  void UpdateCacheAndViewForFolder(nsIMsgFolder *folder, nsMsgKey *newHits,
-                                   uint32_t numNewHits);
+  void UpdateCacheAndViewForFolder(nsIMsgFolder *folder,
+                                   nsTArray<nsMsgKey> const &newHits);
   void RemovePendingDBListeners();
 
  protected:
   virtual nsresult GetMessageEnumerator(
       nsISimpleEnumerator **enumerator) override;
 
   // array index of next folder with cached hits to deal with.
   uint32_t m_cachedFolderArrayIndex;
--- a/mailnews/db/msgdb/public/nsIMsgDatabase.idl
+++ b/mailnews/db/msgdb/public/nsIMsgDatabase.idl
@@ -540,15 +540,22 @@ interface nsIMsgDatabase : nsIDBChangeAn
 
   /**
    * The list of messages currently in the NEW state.
    */
   Array<nsMsgKey> getNewList();
 
   // These are used for caching search hits in a db, to speed up saved search folders.
   nsISimpleEnumerator getCachedHits(in string aSearchFolderUri);
-  void refreshCache(in string aSearchFolderUri, in unsigned long aNumKeys, [array, size_is (aNumKeys)] in nsMsgKey aNewHits,
-     out unsigned long aNumBadHits, [array, size_is(aNumBadHits)] out nsMsgKey aStaleHits);
+
+  /**
+   * Update search cache to ensure it contains aNewHits.
+   *
+   * @param aSearchFolderUri the target folder.
+   * @param aNewHits sorted list of new message keys.
+   * @returns list of keys of messages removed from cache.
+   */
+  Array<nsMsgKey> refreshCache(in string aSearchFolderUri, in Array<nsMsgKey> aNewHits);
   void updateHdrInCache(in string aSearchFolderUri, in nsIMsgDBHdr aHdr, in boolean aAdd);
   boolean hdrIsInCache(in string aSearchFolderUri, in nsIMsgDBHdr aHdr);
 
 };
 /** @} */
--- a/mailnews/db/msgdb/src/nsMsgDatabase.cpp
+++ b/mailnews/db/msgdb/src/nsMsgDatabase.cpp
@@ -5114,85 +5114,78 @@ nsMsgDatabase::GetCachedHits(const char 
   (void)GetSearchResultsTable(aSearchFolderUri, false, getter_AddRefs(table));
   if (!table) return NS_ERROR_FAILURE;  // expected result for no cached hits
   NS_ADDREF(*aEnumerator =
                 new nsMsgDBEnumerator(this, table, nullptr, nullptr));
   return NS_OK;
 }
 
 NS_IMETHODIMP nsMsgDatabase::RefreshCache(const char *aSearchFolderUri,
-                                          uint32_t aNumKeys, nsMsgKey *aNewHits,
-                                          uint32_t *aNumBadHits,
-                                          nsMsgKey **aStaleHits) {
+                                          nsTArray<nsMsgKey> const &aNewHits,
+                                          nsTArray<nsMsgKey> &aStaleHits) {
   nsCOMPtr<nsIMdbTable> table;
   nsresult err =
       GetSearchResultsTable(aSearchFolderUri, true, getter_AddRefs(table));
   NS_ENSURE_SUCCESS(err, err);
   // update the table so that it just contains aNewHits.
   // And, keep track of the headers in the original table but not in aNewHits,
   // so we can put those in aStaleHits. both aNewHits and the db table are
   // sorted by uid/key. So, start at the beginning of the table and the aNewHits
   // array.
   uint32_t newHitIndex = 0;
   uint32_t tableRowIndex = 0;
 
   uint32_t rowCount;
   table->GetCount(GetEnv(), &rowCount);
-  nsTArray<nsMsgKey> staleHits;
+  aStaleHits.Clear();
   // should assert that each array is sorted
-  while (newHitIndex < aNumKeys || tableRowIndex < rowCount) {
+  while (newHitIndex < aNewHits.Length() || tableRowIndex < rowCount) {
     mdbOid oid;
     nsMsgKey tableRowKey = nsMsgKey_None;
     if (tableRowIndex < rowCount) {
       nsresult ret = table->PosToOid(GetEnv(), tableRowIndex, &oid);
       if (NS_FAILED(ret)) {
         tableRowIndex++;
         continue;
       }
       tableRowKey =
           oid.mOid_Id;  // ### TODO need the real key for the 0th key problem.
     }
 
-    if (newHitIndex < aNumKeys && aNewHits[newHitIndex] == tableRowKey) {
+    if (newHitIndex < aNewHits.Length() &&
+        aNewHits[newHitIndex] == tableRowKey) {
       newHitIndex++;
       tableRowIndex++;
       continue;
     } else if (tableRowIndex >= rowCount ||
-               (newHitIndex < aNumKeys &&
+               (newHitIndex < aNewHits.Length() &&
                 aNewHits[newHitIndex] < tableRowKey)) {
       nsCOMPtr<nsIMdbRow> hdrRow;
       mdbOid rowObjectId;
 
       rowObjectId.mOid_Id = aNewHits[newHitIndex];
       rowObjectId.mOid_Scope = m_hdrRowScopeToken;
       err = m_mdbStore->GetRow(GetEnv(), &rowObjectId, getter_AddRefs(hdrRow));
       if (hdrRow) {
         table->AddRow(GetEnv(), hdrRow);
         mdb_pos newPos;
         table->MoveRow(GetEnv(), hdrRow, rowCount, tableRowIndex, &newPos);
         rowCount++;
         tableRowIndex++;
       }
       newHitIndex++;
       continue;
-    } else if (newHitIndex >= aNumKeys || aNewHits[newHitIndex] > tableRowKey) {
-      staleHits.AppendElement(tableRowKey);
+    } else if (newHitIndex >= aNewHits.Length() ||
+               aNewHits[newHitIndex] > tableRowKey) {
+      aStaleHits.AppendElement(tableRowKey);
       table->CutOid(GetEnv(), &oid);
       rowCount--;
       continue;  // don't increment tableRowIndex since we removed that row.
     }
   }
-  *aNumBadHits = staleHits.Length();
-  if (*aNumBadHits) {
-    *aStaleHits =
-        static_cast<nsMsgKey *>(moz_xmalloc(*aNumBadHits * sizeof(nsMsgKey)));
-    if (!*aStaleHits) return NS_ERROR_OUT_OF_MEMORY;
-    memcpy(*aStaleHits, staleHits.Elements(), *aNumBadHits * sizeof(nsMsgKey));
-  } else
-    *aStaleHits = nullptr;
 
 #ifdef DEBUG_David_Bienvenu
   printf("after refreshing cache\n");
   // iterate over table and assert that it's in id order
   table->GetCount(GetEnv(), &rowCount);
   mdbOid oid;
   tableRowIndex = 0;
   mdb_id prevId = 0;