Bug 616090 - Optimize timer in nsDOMStorageDBWrapper. r=honzab a=blocking-fennec
authorAlon Zakai <azakai@mozilla.com>
Thu, 16 Dec 2010 10:09:58 -0800
changeset 59411 ff47addbc1bfa1a3af426bd5c3633e103378260c
parent 59410 18a8c936ce3338c39e15ead4a151470c9d10b774
child 59412 8b6d5951bc1d1cd30ca451eae3c9ee0fdb45e494
push id1
push usershaver@mozilla.com
push dateTue, 04 Jan 2011 17:58:04 +0000
reviewershonzab, blocking-fennec
bugs616090
milestone2.0b9pre
Bug 616090 - Optimize timer in nsDOMStorageDBWrapper. r=honzab a=blocking-fennec
dom/src/storage/nsDOMStorage.cpp
dom/src/storage/nsDOMStorage.h
dom/src/storage/nsDOMStorageDBWrapper.cpp
dom/src/storage/nsDOMStorageDBWrapper.h
--- a/dom/src/storage/nsDOMStorage.cpp
+++ b/dom/src/storage/nsDOMStorage.cpp
@@ -436,16 +436,18 @@ nsDOMStorageManager::Observe(nsISupports
 
       return DOMStorageImpl::gStorageDB->DropSessionOnlyStoragesForHost(host);
 #endif
     }
   } else if (!strcmp(aTopic, "timer-callback")) {
     nsCOMPtr<nsIObserverService> obsserv = mozilla::services::GetObserverService();
     if (obsserv)
       obsserv->NotifyObservers(nsnull, NS_DOMSTORAGE_FLUSH_TIMER_OBSERVER, nsnull);
+    if (!UnflushedDataExists())
+      DOMStorageImpl::gStorageDB->StopTempTableFlushTimer();
   } else if (!strcmp(aTopic, "browser:purge-domain-data")) {
     // Convert the domain name to the ACE format
     nsCAutoString aceDomain;
     nsresult rv;
     nsCOMPtr<nsIIDNService> converter = do_GetService(NS_IDNSERVICE_CONTRACTID);
     if (converter) {
       rv = converter->ConvertUTF8toACE(NS_ConvertUTF16toUTF8(aData), aceDomain);
       NS_ENSURE_SUCCESS(rv, rv);
@@ -532,16 +534,36 @@ nsDOMStorageManager::AddToStoragesHash(D
 void
 nsDOMStorageManager::RemoveFromStoragesHash(DOMStorageImpl* aStorage)
 {
   nsDOMStorageEntry* entry = mStorages.GetEntry(aStorage);
   if (entry)
     mStorages.RemoveEntry(aStorage);
 }
 
+static PLDHashOperator
+CheckUnflushedData(nsDOMStorageEntry* aEntry, void* userArg)
+{
+  if (aEntry->mStorage->WasTemporaryTableLoaded()) {
+    PRBool *unflushedData = (PRBool*)userArg;
+    *unflushedData = PR_TRUE;
+    return PL_DHASH_STOP;
+  }
+
+  return PL_DHASH_NEXT;
+}
+
+PRBool
+nsDOMStorageManager::UnflushedDataExists()
+{
+  PRBool unflushedData = PR_FALSE;
+  mStorages.EnumerateEntries(CheckUnflushedData, &unflushedData);
+  return unflushedData;
+}
+
 //
 // nsDOMStorage
 //
 
 #ifdef MOZ_STORAGE
 nsDOMStorageDBWrapper* DOMStorageImpl::gStorageDB = nsnull;
 #endif
 
@@ -1050,16 +1072,18 @@ DOMStorageImpl::WasTemporaryTableLoaded(
 
 void
 DOMStorageImpl::SetTemporaryTableLoaded(bool loaded)
 {
   if (loaded) {
     mLastTemporaryTableAccessTime = TimeStamp::Now();
     if (!mLoadedTemporaryTable)
       mTemporaryTableAge = mLastTemporaryTableAccessTime;
+
+    gStorageDB->EnsureTempTableFlushTimer();
   }
 
   mLoadedTemporaryTable = loaded;
 }
 
 NS_IMETHODIMP
 DOMStorageImpl::Observe(nsISupports *subject,
                       const char *topic,
--- a/dom/src/storage/nsDOMStorage.h
+++ b/dom/src/storage/nsDOMStorage.h
@@ -131,16 +131,21 @@ public:
   nsresult ClearAllStorages();
 
   PRBool InPrivateBrowsingMode() { return mInPrivateBrowsing; }
 
   static nsresult Initialize();
   static nsDOMStorageManager* GetInstance();
   static void Shutdown();
 
+  /**
+   * Checks whether there is any data waiting to be flushed from a temp table.
+   */
+  PRBool UnflushedDataExists();
+
   static nsDOMStorageManager* gStorageManager;
 
 protected:
 
   nsTHashtable<nsDOMStorageEntry> mStorages;
   PRBool mInPrivateBrowsing;
 };
 
--- a/dom/src/storage/nsDOMStorageDBWrapper.cpp
+++ b/dom/src/storage/nsDOMStorageDBWrapper.cpp
@@ -70,19 +70,17 @@ void ReverseString(const nsCSubstring& s
 }
 
 nsDOMStorageDBWrapper::nsDOMStorageDBWrapper()
 {
 }
 
 nsDOMStorageDBWrapper::~nsDOMStorageDBWrapper()
 {
-  if (mFlushTimer) {
-    mFlushTimer->Cancel();
-  }
+  StopTempTableFlushTimer();
 }
 
 nsresult
 nsDOMStorageDBWrapper::Init()
 {
   nsresult rv;
 
   rv = mPersistentDB.Init(NS_LITERAL_STRING("webappsstore.sqlite"));
@@ -92,23 +90,16 @@ nsDOMStorageDBWrapper::Init()
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = mSessionOnlyDB.Init(&mPersistentDB);
   NS_ENSURE_SUCCESS(rv, rv);
 
   rv = mPrivateBrowsingDB.Init();
   NS_ENSURE_SUCCESS(rv, rv);
 
-  mFlushTimer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  rv = mFlushTimer->Init(nsDOMStorageManager::gStorageManager, 5000,
-                         nsITimer::TYPE_REPEATING_SLACK);
-  NS_ENSURE_SUCCESS(rv, rv);
-
   return NS_OK;
 }
 
 nsresult
 nsDOMStorageDBWrapper::EnsureLoadTemporaryTableForStorage(DOMStorageImpl* aStorage)
 {
   if (aStorage->CanUseChromePersist())
     return mChromePersistentDB.EnsureLoadTemporaryTableForStorage(aStorage);
@@ -447,8 +438,35 @@ nsDOMStorageDBWrapper::GetDomainFromScop
 {
   nsCAutoString reverseDomain, scope;
   scope = aScope;
   scope.Left(reverseDomain, scope.FindChar(':')-1);
 
   ReverseString(reverseDomain, aDomain);
   return NS_OK;
 }
+
+void
+nsDOMStorageDBWrapper::EnsureTempTableFlushTimer()
+{
+  if (!mTempTableFlushTimer) {
+    nsresult rv;
+    mTempTableFlushTimer = do_CreateInstance(NS_TIMER_CONTRACTID, &rv);
+
+    if (!NS_SUCCEEDED(rv)) {
+      mTempTableFlushTimer = nsnull;
+      return;
+    }
+
+    mTempTableFlushTimer->Init(nsDOMStorageManager::gStorageManager, 5000,
+                               nsITimer::TYPE_REPEATING_SLACK);
+  }
+}
+
+void
+nsDOMStorageDBWrapper::StopTempTableFlushTimer()
+{
+  if (mTempTableFlushTimer) {
+    mTempTableFlushTimer->Cancel();
+    mTempTableFlushTimer = nsnull;
+  }
+}
+
--- a/dom/src/storage/nsDOMStorageDBWrapper.h
+++ b/dom/src/storage/nsDOMStorageDBWrapper.h
@@ -216,18 +216,29 @@ public:
     */
   static nsresult CreateQuotaDomainDBKey(const nsACString& aAsciiDomain,
                                          PRBool aIncludeSubDomains, PRBool aETLDplus1Only,
                                          nsACString& aKey);
 
   static nsresult GetDomainFromScopeKey(const nsACString& aScope,
                                          nsACString& aDomain);
 
+  /**
+   * Ensures the temp table flush timer is running. This is called when we add
+   * data that will need to be flushed.
+   */
+  void EnsureTempTableFlushTimer();
+
+  /**
+   * Stops the temp table flush timer.
+   */
+  void StopTempTableFlushTimer();
+
 protected:
   nsDOMStoragePersistentDB mChromePersistentDB;
   nsDOMStoragePersistentDB mPersistentDB;
   nsDOMStorageMemoryDB mSessionOnlyDB;
   nsDOMStorageMemoryDB mPrivateBrowsingDB;
 
-  nsCOMPtr<nsITimer> mFlushTimer;
+  nsCOMPtr<nsITimer> mTempTableFlushTimer;
 };
 
 #endif /* nsDOMStorageDB_h___ */