Make open transactions keep their DB thread alive
authorBen Turner <bent.mozilla@gmail.com>
Thu, 20 May 2010 15:47:34 -0700
changeset 44009 293a2363e51a49e9ea8ed83e389e3f1ff812143d
parent 44008 baba9a7e51a1ee4f5d6d8b2690ec4cf21e311ad6
child 44010 c76bff054d7965aae52de76081a25c6392408f59
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone1.9.3a5pre
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
Make open transactions keep their DB thread alive
dom/indexedDB/IDBDatabaseRequest.h
dom/indexedDB/IDBTransactionRequest.cpp
dom/indexedDB/IndexedDatabaseRequest.cpp
dom/indexedDB/LazyIdleThread.cpp
dom/indexedDB/LazyIdleThread.h
--- a/dom/indexedDB/IDBDatabaseRequest.h
+++ b/dom/indexedDB/IDBDatabaseRequest.h
@@ -163,16 +163,24 @@ public:
   }
 
   void FireCloseConnectionRunnable();
 
   void OnVersionSet(const nsString& aVersion);
   void OnObjectStoreCreated(const ObjectStoreInfo& aInfo);
   void OnObjectStoreRemoved(const ObjectStoreInfo& aInfo);
 
+  void DisableConnectionThreadTimeout() {
+    mConnectionThread->DisableIdleTimeout();
+  }
+
+  void EnableConnectionThreadTimeout() {
+    mConnectionThread->EnableIdleTimeout();
+  }
+
 protected:
   IDBDatabaseRequest();
   ~IDBDatabaseRequest();
 
   // Only meant to be called on mStorageThread!
   nsCOMPtr<mozIStorageConnection>& Connection();
 
   // Only meant to be called on mStorageThread!
--- a/dom/indexedDB/IDBTransactionRequest.cpp
+++ b/dom/indexedDB/IDBTransactionRequest.cpp
@@ -79,26 +79,30 @@ IDBTransactionRequest::~IDBTransactionRe
 {
   NS_ASSERTION(!mPendingRequests, "Should have no pending requests here!");
 }
 
 void
 IDBTransactionRequest::OnNewRequest()
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
+  if (!mPendingRequests) {
+    mDatabase->DisableConnectionThreadTimeout();
+  }
   ++mPendingRequests;
 }
 
 void
 IDBTransactionRequest::OnRequestFinished()
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(mPendingRequests, "Mismatched calls!");
   --mPendingRequests;
   if (!mPendingRequests) {
+    mDatabase->EnableConnectionThreadTimeout();
     // Commit!
     NS_NOTYETIMPLEMENTED("Implement me!");
   }
 }
 
 NS_IMPL_CYCLE_COLLECTION_CLASS(IDBTransactionRequest)
 
 NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(IDBTransactionRequest,
--- a/dom/indexedDB/IndexedDatabaseRequest.cpp
+++ b/dom/indexedDB/IndexedDatabaseRequest.cpp
@@ -58,17 +58,17 @@
 #include "LazyIdleThread.h"
 
 #define DB_SCHEMA_VERSION 1
 
 USING_INDEXEDDB_NAMESPACE
 
 namespace {
 
-const PRUint32 kDefaultThreadTimeoutMS = 30000;
+const PRUint32 kDefaultThreadTimeoutMS = 5000;
 
 class OpenDatabaseHelper : public AsyncConnectionHelper
 {
 public:
   OpenDatabaseHelper(IDBRequest* aRequest,
                      const nsAString& aName,
                      const nsAString& aDescription,
                      const nsACString& aASCIIOrigin,
--- a/dom/indexedDB/LazyIdleThread.cpp
+++ b/dom/indexedDB/LazyIdleThread.cpp
@@ -67,17 +67,18 @@ LazyIdleThread::LazyIdleThread(PRUint32 
                                nsIObserver* aIdleObserver)
 : mMutex("LazyIdleThread::mMutex"),
   mOwningThread(NS_GetCurrentThread()),
   mIdleObserver(aIdleObserver),
   mIdleTimeoutMS(aIdleTimeoutMS),
   mPendingEventCount(0),
   mIdleNotificationCount(0),
   mShutdown(PR_FALSE),
-  mThreadIsShuttingDown(PR_FALSE)
+  mThreadIsShuttingDown(PR_FALSE),
+  mIdleTimeoutEnabled(PR_TRUE)
 {
   NS_ASSERTION(mOwningThread, "This should never fail!");
 }
 
 LazyIdleThread::~LazyIdleThread()
 {
   ASSERT_OWNING_THREAD();
 
@@ -94,16 +95,60 @@ LazyIdleThread::SetWeakIdleObserver(nsIO
                      "Setting an observer after Shutdown was called!");
     return;
   }
 
   mIdleObserver = aObserver;
 }
 
 void
+LazyIdleThread::DisableIdleTimeout()
+{
+  ASSERT_OWNING_THREAD();
+  if (!mIdleTimeoutEnabled) {
+    return;
+  }
+  mIdleTimeoutEnabled = PR_FALSE;
+
+  if (mIdleTimer && NS_FAILED(mIdleTimer->Cancel())) {
+    NS_WARNING("Failed to cancel timer!");
+  }
+
+  MutexAutoLock lock(mMutex);
+
+  // Pretend we have a pending event to keep the idle timer from firing.
+  NS_ASSERTION(mPendingEventCount < PR_UINT32_MAX, "Way too many!");
+  mPendingEventCount++;
+}
+
+void
+LazyIdleThread::EnableIdleTimeout()
+{
+  ASSERT_OWNING_THREAD();
+  if (mIdleTimeoutEnabled) {
+    return;
+  }
+  mIdleTimeoutEnabled = PR_TRUE;
+
+  {
+    MutexAutoLock lock(mMutex);
+
+    NS_ASSERTION(mPendingEventCount, "Mismatched calls to observer methods!");
+    --mPendingEventCount;
+  }
+
+  if (mThread) {
+    nsCOMPtr<nsIRunnable> runnable(new nsRunnable());
+    if (NS_FAILED(Dispatch(runnable, NS_DISPATCH_NORMAL))) {
+      NS_WARNING("Failed to dispatch!");
+    }
+  }
+}
+
+void
 LazyIdleThread::PreDispatch()
 {
   MutexAutoLock lock(mMutex);
 
   NS_ASSERTION(mPendingEventCount < PR_UINT32_MAX, "Way too many!");
   mPendingEventCount++;
 }
 
--- a/dom/indexedDB/LazyIdleThread.h
+++ b/dom/indexedDB/LazyIdleThread.h
@@ -85,16 +85,27 @@ public:
    * that can be used to post cleanup events. The aTopic argument will be
    * IDLE_THREAD_TOPIC, and aData will be null. The LazyIdleThread does not add
    * a reference to the observer to avoid circular references as it is assumed
    * to be the owner. It is the caller's responsibility to clear this observer
    * if the pointer becomes invalid.
    */
   void SetWeakIdleObserver(nsIObserver* aObserver);
 
+  /**
+   * Disable the idle timeout for this thread. No effect if the timeout is
+   * already disabled.
+   */
+  void DisableIdleTimeout();
+
+  /**
+   * Enable the idle timeout. No effect if the timeout is already enabled.
+   */
+  void EnableIdleTimeout();
+
 private:
   /**
    * Calls Shutdown().
    */
   ~LazyIdleThread();
 
   /**
    * Called just before dispatching to mThread.
@@ -186,13 +197,18 @@ private:
    */
   PRPackedBool mShutdown;
 
   /**
    * Set from CleanupThread and lasting until the thread has shut down. Prevents
    * further idle notifications during the shutdown process.
    */
   PRPackedBool mThreadIsShuttingDown;
+
+  /**
+   * Whether or not the idle timeout is enabled.
+   */
+  PRPackedBool mIdleTimeoutEnabled;
 };
 
 END_INDEXEDDB_NAMESPACE
 
 #endif // mozilla_dom_indexeddb_lazyidlethread_h__