Use sqlite3_unlock_notify() to prevent concurrent writers from crapping out
authorBen Turner <bent.mozilla@gmail.com>
Fri, 28 May 2010 16:57:07 -0700
changeset 44028 9513de41e9208274cc7311db9595035958704e67
parent 44027 979de20a4378c573732f9c791884050c17b60dfa
child 44029 820aa282e28ee58ef78ba8a26f8a1726468a090d
push id13972
push userbturner@mozilla.com
push dateTue, 22 Jun 2010 03:19:22 +0000
treeherdermozilla-central@89aaaa116328 [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
Use sqlite3_unlock_notify() to prevent concurrent writers from crapping out
configure.in
db/sqlite3/src/Makefile.in
dom/indexedDB/AsyncConnectionHelper.cpp
dom/indexedDB/IndexedDatabaseRequest.cpp
dom/indexedDB/test/test_overlapping_transactions.html
storage/src/Makefile.in
storage/src/SharedCacheUnlockNotify.cpp
storage/src/SharedCacheUnlockNotify.h
storage/src/mozStorageAsyncStatement.cpp
storage/src/mozStorageAsyncStatementExecution.cpp
storage/src/mozStorageConnection.cpp
storage/src/mozStorageStatement.cpp
--- a/configure.in
+++ b/configure.in
@@ -6589,16 +6589,45 @@ else
         )
     ])
     AC_MSG_RESULT($ac_cv_sqlite_enable_fts3)
     CFLAGS="$_SAVE_CFLAGS"
     LIBS="$_SAVE_LIBS"
     if test "x$ac_cv_sqlite_enable_fts3" = "xno"; then
         AC_MSG_ERROR([System SQLite library is not compiled with SQLITE_ENABLE_FTS3.])
     fi
+
+    dnl ================================
+    dnl === SQLITE_ENABLE_UNLOCK_NOTIFY check ===
+    dnl ================================
+    dnl check to see if the system SQLite package is compiled with
+    dnl SQLITE_ENABLE_UNLOCK_NOTIFY enabled.
+    AC_MSG_CHECKING(for SQLITE_ENABLE_UNLOCK_NOTIFY support in system SQLite)
+    _SAVE_CFLAGS="$CFLAGS"
+    CFLAGS="$CFLAGS $SQLITE_CFLAGS"
+    _SAVE_LIBS="$LIBS"
+    LIBS="$LIBS $SQLITE_LIBS"
+    AC_CACHE_VAL(ac_cv_sqlite_enable_unlock_notify,[
+        AC_TRY_RUN([
+            #include "sqlite3.h"
+
+            int main(int argc, char **argv){
+              return !sqlite3_compileoption_used("SQLITE_ENABLE_UNLOCK_NOTIFY");
+            }],
+            ac_cv_sqlite_enable_unlock_notify=yes,
+            ac_cv_sqlite_enable_unlock_notify=no,
+            ac_cv_sqlite_enable_unlock_notify=no
+        )
+    ])
+    AC_MSG_RESULT($ac_cv_sqlite_enable_unlock_notify)
+    CFLAGS="$_SAVE_CFLAGS"
+    LIBS="$_SAVE_LIBS"
+    if test "x$ac_cv_sqlite_enable_unlock_notify" = "xno"; then
+        AC_MSG_ERROR([System SQLite library is not compiled with SQLITE_ENABLE_UNLOCK_NOTIFY.])
+    fi
 fi
 
 AC_SUBST(MOZ_NATIVE_SQLITE)
 
 dnl ========================================================
 dnl = Enable help viewer (off by default)
 dnl ========================================================
 if test -n "$MOZ_HELP_VIEWER"; then
--- a/db/sqlite3/src/Makefile.in
+++ b/db/sqlite3/src/Makefile.in
@@ -101,16 +101,17 @@ CSRCS = \
 # -DSQLITE_ENABLE_FTS3=1 enables the full-text index module.
 # -DSQLITE_CORE=1 statically links that module into the SQLite library.
 # Note: Be sure to update the configure.in checks when these change!
 DEFINES = \
   -DSQLITE_SECURE_DELETE=1 \
   -DSQLITE_THREADSAFE=1 \
   -DSQLITE_CORE=1 \
   -DSQLITE_ENABLE_FTS3=1 \
+  -DSQLITE_ENABLE_UNLOCK_NOTIFY=1 \
   $(NULL)
 
 # -DSQLITE_ENABLE_LOCKING_STYLE=1 to help with AFP folders
 ifeq ($(MOZ_WIDGET_TOOLKIT),cocoa)
 DEFINES += -DSQLITE_ENABLE_LOCKING_STYLE=1
 endif
 
 # Turn on SQLite's assertions in debug builds.
--- a/dom/indexedDB/AsyncConnectionHelper.cpp
+++ b/dom/indexedDB/AsyncConnectionHelper.cpp
@@ -100,18 +100,19 @@ AsyncConnectionHelper::AsyncConnectionHe
 {
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   NS_ASSERTION(mRequest, "Null request!");
 }
 
 AsyncConnectionHelper::~AsyncConnectionHelper()
 {
   if (!NS_IsMainThread()) {
-    NS_ASSERTION(mErrorCode == NOREPLY,
-                 "This should only happen if NOREPLY was returned!");
+    NS_ASSERTION(mErrorCode == NOREPLY || !mRequest,
+                 "This should only happen if NOREPLY was returned or if the "
+                 "runnable already ran on the main thread!");
 
     IDBDatabaseRequest* database;
     mDatabase.forget(&database);
 
     IDBTransactionRequest* transaction;
     mTransaction.forget(&transaction);
 
     IDBRequest* request;
--- a/dom/indexedDB/IndexedDatabaseRequest.cpp
+++ b/dom/indexedDB/IndexedDatabaseRequest.cpp
@@ -445,17 +445,17 @@ IndexedDatabaseRequest::GetConnection(co
   NS_ENSURE_TRUE(exists, nsnull);
 
   nsCOMPtr<mozIStorageService> ss =
     do_GetService(MOZ_STORAGE_SERVICE_CONTRACTID);
   NS_ENSURE_TRUE(ss, nsnull);
 
   nsCOMPtr<mozIStorageConnection> connection;
   rv = ss->OpenDatabase(dbFile, getter_AddRefs(connection));
-  NS_ENSURE_TRUE(ss, nsnull);
+  NS_ENSURE_SUCCESS(rv, nsnull);
 
 #ifdef DEBUG
   {
     // Check to make sure that the database schema is correct again.
     PRInt32 schemaVersion;
     NS_ASSERTION(NS_SUCCEEDED(connection->GetSchemaVersion(&schemaVersion)) &&
                  schemaVersion == DB_SCHEMA_VERSION,
                  "Wrong schema!");
--- a/dom/indexedDB/test/test_overlapping_transactions.html
+++ b/dom/indexedDB/test/test_overlapping_transactions.html
@@ -36,50 +36,52 @@
           }
         };
       }
       yield;
 
       is(db.objectStoreNames.length, objectStores.length,
          "Correct objectStoreNames list");
 
-      let stepNumber = 0;
+      for (let i = 0; i < 50; i++) {
+        let stepNumber = 0;
 
-      request = db.transaction(["foo"], READ_WRITE)
-                  .objectStore("foo")
-                  .add({});
-      request.onerror = errorHandler;
-      request.onsuccess = function(event) {
-        ok(stepNumber == 1 || stepNumber == 2, "This callback came before 3");
-        stepNumber++;
-      }
+        request = db.transaction(["foo"], READ_WRITE)
+                    .objectStore("foo")
+                    .add({});
+        request.onerror = errorHandler;
+        request.onsuccess = function(event) {
+          ok(stepNumber == 1 || stepNumber == 2, "This callback came before 3");
+          stepNumber++;
+        }
 
-      request = db.transaction(["foo", "bar"], READ_WRITE)
-                  .objectStore("bar")
-                  .add({});
-      request.onerror = errorHandler;
-      request.onsuccess = function(event) {
-        is(stepNumber, 3, "This callback came in at 3");
-        stepNumber++;
-        testGenerator.next();
-      }
+        request = db.transaction(["foo", "bar"], READ_WRITE)
+                    .objectStore("bar")
+                    .add({});
+        request.onerror = errorHandler;
+        request.onsuccess = function(event) {
+          is(stepNumber, 3, "This callback came in at 3");
+          stepNumber++;
+          testGenerator.next();
+        }
 
-      request = db.transaction(["bar"], READ_WRITE)
-                  .objectStore("bar")
-                  .add({});
-      request.onerror = errorHandler;
-      request.onsuccess = function(event) {
-        ok(stepNumber == 1 || stepNumber == 2, "This callback came before 3");
+        request = db.transaction(["bar"], READ_WRITE)
+                    .objectStore("bar")
+                    .add({});
+        request.onerror = errorHandler;
+        request.onsuccess = function(event) {
+          ok(stepNumber == 1 || stepNumber == 2, "This callback came before 3");
+          stepNumber++;
+        }
+
         stepNumber++;
-      }
+        yield;
 
-      stepNumber++;
-      yield;
-
-      is(stepNumber, 4, "All callbacks received");
+        is(stepNumber, 4, "All callbacks received");
+      }
 
       finishTest();
       yield;
     }
   </script>
   <script type="text/javascript;version=1.7" src="helpers.js"></script>
 
 </head>
--- a/storage/src/Makefile.in
+++ b/storage/src/Makefile.in
@@ -73,16 +73,17 @@ CPPSRCS = \
   mozStorageAsyncStatementExecution.cpp \
   mozStorageStatementJSHelper.cpp \
   mozStoragePrivateHelpers.cpp \
   mozStorageBindingParamsArray.cpp \
   mozStorageBindingParams.cpp \
   mozStorageAsyncStatement.cpp \
   mozStorageAsyncStatementJSHelper.cpp \
   mozStorageAsyncStatementParams.cpp \
+  SharedCacheUnlockNotify.cpp \
   StorageBaseStatementInternal.cpp \
   SQLCollations.cpp \
   $(NULL)
 
 LOCAL_INCLUDES = \
 	$(SQLITE_CFLAGS)
 
 # This is the default value.  If we ever change it when compiling sqlite, we
new file mode 100644
--- /dev/null
+++ b/storage/src/SharedCacheUnlockNotify.cpp
@@ -0,0 +1,167 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Indexed Database.
+ *
+ * The Initial Developer of the Original Code is
+ * The Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Ben Turner <bent.mozilla@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+/**
+ * This code is heavily based on the sample at:
+ *   http://www.sqlite.org/unlock_notify.html
+ */
+
+#include "SharedCacheUnlockNotify.h"
+
+#include "mozilla/Mutex.h"
+#include "mozilla/CondVar.h"
+#include "nsThreadUtils.h"
+
+namespace {
+
+class UnlockNotification
+{
+public:
+  UnlockNotification()
+  : mMutex("UnlockNotification mMutex"),
+    mCondVar(mMutex, "UnlockNotification condVar"),
+    mSignaled(false)
+  { }
+
+  void Wait()
+  {
+    mozilla::MutexAutoLock lock(mMutex);
+    while (!mSignaled) {
+      mCondVar.Wait();
+    }
+  }
+
+  void Signal()
+  {
+    mozilla::MutexAutoLock lock(mMutex);
+    mSignaled = true;
+    mCondVar.Notify();
+  }
+
+private:
+  mozilla::Mutex mMutex;
+  mozilla::CondVar mCondVar;
+  bool mSignaled;
+};
+
+void
+UnlockNotifyCallback(void** apArg,
+                     int nArg)
+{
+  for (int i = 0; i < nArg; i++) {
+    UnlockNotification* notification =
+      static_cast<UnlockNotification*>(apArg[i]);
+    notification->Signal();
+  }
+}
+
+int
+WaitForUnlockNotify(sqlite3* db)
+{
+  UnlockNotification notification;
+  int srv = ::sqlite3_unlock_notify(db, UnlockNotifyCallback, &notification);
+  NS_ASSERTION(srv == SQLITE_LOCKED || srv == SQLITE_OK, "Bad result!");
+
+  if (srv == SQLITE_OK) {
+    notification.Wait();
+  }
+
+  return srv;
+}
+
+} // anonymous namespace
+
+namespace mozilla {
+namespace storage {
+
+int
+moz_sqlite3_step(sqlite3_stmt* pStmt)
+{
+  bool checkedMainThread = false;
+
+  int srv;
+  while ((srv = ::sqlite3_step(pStmt)) == SQLITE_LOCKED) {
+    if (!checkedMainThread) {
+      checkedMainThread = true;
+      if (NS_IsMainThread()) {
+        NS_WARNING("We won't allow blocking on the main thread!");
+        break;
+      }
+    }
+
+    srv = WaitForUnlockNotify(sqlite3_db_handle(pStmt));
+    if (srv != SQLITE_OK)
+      break;
+
+    sqlite3_reset(pStmt);
+  }
+
+  return srv;
+}
+
+int
+moz_sqlite3_prepare_v2(sqlite3* db,
+                       const char* zSql,
+                       int nByte,
+                       sqlite3_stmt** ppStmt,
+                       const char** pzTail)
+{
+  bool checkedMainThread = false;
+
+  int srv;
+  while((srv = ::sqlite3_prepare_v2(db, zSql, nByte, ppStmt, pzTail)) ==
+        SQLITE_LOCKED) {
+    if (!checkedMainThread) {
+      checkedMainThread = true;
+      if (NS_IsMainThread()) {
+        NS_WARNING("We won't allow blocking on the main thread!");
+        break;
+      }
+    }
+
+    srv = WaitForUnlockNotify(db);
+    if (srv != SQLITE_OK)
+      break;
+  }
+
+  return srv;
+}
+
+} /* namespace storage */
+} /* namespace mozilla */
new file mode 100644
--- /dev/null
+++ b/storage/src/SharedCacheUnlockNotify.h
@@ -0,0 +1,59 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=2 et sw=2 tw=80: */
+/* ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Indexed Database.
+ *
+ * The Initial Developer of the Original Code is
+ * The Mozilla Foundation.
+ * Portions created by the Initial Developer are Copyright (C) 2010
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Ben Turner <bent.mozilla@gmail.com>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef _sharedCacheUnlockNotify_h_
+#define _sharedCacheUnlockNotify_h_
+
+#include "sqlite3.h"
+
+namespace mozilla {
+namespace storage {
+
+extern int moz_sqlite3_step(sqlite3_stmt* pStmt);
+
+extern int moz_sqlite3_prepare_v2(sqlite3* db,
+                                  const char* zSql,
+                                  int nByte,
+                                  sqlite3_stmt** ppStmt,
+                                  const char** pzTail);
+
+} /* namespace storage */
+} /* namespace mozilla */
+
+#endif /* _sharedCacheUnlockNotify_h_ */
--- a/storage/src/mozStorageAsyncStatement.cpp
+++ b/storage/src/mozStorageAsyncStatement.cpp
@@ -53,16 +53,17 @@
 
 #include "mozStorageBindingParams.h"
 #include "mozStorageConnection.h"
 #include "mozStorageAsyncStatementJSHelper.h"
 #include "mozStorageAsyncStatementParams.h"
 #include "mozStoragePrivateHelpers.h"
 #include "mozStorageStatementRow.h"
 #include "mozStorageStatement.h"
+#include "SharedCacheUnlockNotify.h"
 
 #include "prlog.h"
 
 #ifdef PR_LOGGING
 extern PRLogModuleInfo *gStorageLog;
 #endif
 
 namespace mozilla {
@@ -327,19 +328,19 @@ AsyncStatement::getAsyncStatement(sqlite
   // Make sure we are never called on the connection's owning thread.
   PRBool onOpenedThread = PR_FALSE;
   (void)mDBConnection->threadOpenedOn->IsOnCurrentThread(&onOpenedThread);
   NS_ASSERTION(!onOpenedThread,
                "We should only be called on the async thread!");
 #endif
 
   if (!mAsyncStatement) {
-    int rc = ::sqlite3_prepare_v2(mDBConnection->GetNativeConnection(),
-                                  mSQLString.get(), -1,
-                                  &mAsyncStatement, NULL);
+    int rc = moz_sqlite3_prepare_v2(mDBConnection->GetNativeConnection(),
+                                    mSQLString.get(), -1,
+                                    &mAsyncStatement, NULL);
     if (rc != SQLITE_OK) {
 #ifdef PR_LOGGING
       PR_LOG(gStorageLog, PR_LOG_ERROR,
              ("Sqlite statement prepare error: %d '%s'", rc,
               ::sqlite3_errmsg(mDBConnection->GetNativeConnection())));
       PR_LOG(gStorageLog, PR_LOG_ERROR,
              ("Statement was: '%s'", mSQLString.get()));
 #endif
--- a/storage/src/mozStorageAsyncStatementExecution.cpp
+++ b/storage/src/mozStorageAsyncStatementExecution.cpp
@@ -47,16 +47,17 @@
 #include "mozStorageHelper.h"
 #include "mozStorageResultSet.h"
 #include "mozStorageRow.h"
 #include "mozStorageConnection.h"
 #include "mozStorageError.h"
 #include "mozStoragePrivateHelpers.h"
 #include "mozStorageStatementData.h"
 #include "mozStorageAsyncStatementExecution.h"
+#include "SharedCacheUnlockNotify.h"
 
 namespace mozilla {
 namespace storage {
 
 /**
  * The following constants help batch rows into result sets.
  * MAX_MILLISECONDS_BETWEEN_RESULTS was chosen because any user-based task that
  * takes less than 200 milliseconds is considered to feel instantaneous to end
@@ -337,17 +338,17 @@ bool
 AsyncExecuteStatements::executeStatement(sqlite3_stmt *aStatement)
 {
   mMutex.AssertNotCurrentThreadOwns();
 
   while (true) {
     // lock the sqlite mutex so sqlite3_errmsg cannot change
     SQLiteMutexAutoLock lockedScope(mDBMutex);
 
-    int rc = ::sqlite3_step(aStatement);
+    int rc = moz_sqlite3_step(aStatement);
     // Stop if we have no more results.
     if (rc == SQLITE_DONE)
       return false;
 
     // If we got results, we can return now.
     if (rc == SQLITE_ROW)
       return true;
 
--- a/storage/src/mozStorageConnection.cpp
+++ b/storage/src/mozStorageConnection.cpp
@@ -61,16 +61,17 @@
 #include "mozStorageSQLFunctions.h"
 #include "mozStorageConnection.h"
 #include "mozStorageService.h"
 #include "mozStorageStatement.h"
 #include "mozStorageAsyncStatement.h"
 #include "mozStorageArgValueArray.h"
 #include "mozStoragePrivateHelpers.h"
 #include "mozStorageStatementData.h"
+#include "SharedCacheUnlockNotify.h"
 #include "StorageBaseStatementInternal.h"
 #include "SQLCollations.h"
 
 #include "prlog.h"
 #include "prprf.h"
 
 #ifdef PR_LOGGING
 PRLogModuleInfo* gStorageLog = nsnull;
@@ -408,20 +409,20 @@ Connection::initialize(nsIFile *aDatabas
     ::sqlite3_close(mDBConn);
     mDBConn = nsnull;
     return convertResultCode(srv);
   }
 
   // Execute a dummy statement to force the db open, and to verify if it is
   // valid or not.
   sqlite3_stmt *stmt;
-  srv = ::sqlite3_prepare_v2(mDBConn, "SELECT * FROM sqlite_master", -1, &stmt,
-                             NULL);
+  srv = moz_sqlite3_prepare_v2(mDBConn, "SELECT * FROM sqlite_master", -1,
+                               &stmt, NULL);
   if (srv == SQLITE_OK) {
-    srv = ::sqlite3_step(stmt);
+    srv = moz_sqlite3_step(stmt);
 
     if (srv == SQLITE_DONE || srv == SQLITE_ROW)
         srv = SQLITE_OK;
     ::sqlite3_finalize(stmt);
   }
 
   if (srv != SQLITE_OK) {
     ::sqlite3_close(mDBConn);
@@ -471,21 +472,21 @@ Connection::databaseElementExists(enum D
       query.Append("table");
       break;
   }
   query.Append("' AND name ='");
   query.Append(aElementName);
   query.Append("'");
 
   sqlite3_stmt *stmt;
-  int srv = ::sqlite3_prepare_v2(mDBConn, query.get(), -1, &stmt, NULL);
+  int srv = moz_sqlite3_prepare_v2(mDBConn, query.get(), -1, &stmt, NULL);
   if (srv != SQLITE_OK)
     return convertResultCode(srv);
 
-  srv = ::sqlite3_step(stmt);
+  srv = moz_sqlite3_step(stmt);
   // we just care about the return value from step
   (void)::sqlite3_finalize(stmt);
 
   if (srv == SQLITE_ROW) {
     *_exists = PR_TRUE;
     return NS_OK;
   }
   if (srv == SQLITE_DONE) {
--- a/storage/src/mozStorageStatement.cpp
+++ b/storage/src/mozStorageStatement.cpp
@@ -53,16 +53,17 @@
 
 #include "mozStorageBindingParams.h"
 #include "mozStorageConnection.h"
 #include "mozStorageStatementJSHelper.h"
 #include "mozStoragePrivateHelpers.h"
 #include "mozStorageStatementParams.h"
 #include "mozStorageStatementRow.h"
 #include "mozStorageStatement.h"
+#include "SharedCacheUnlockNotify.h"
 
 #include "prlog.h"
 
 #ifdef PR_LOGGING
 extern PRLogModuleInfo* gStorageLog;
 #endif
 
 namespace mozilla {
@@ -168,18 +169,18 @@ Statement::initialize(Connection *aDBCon
                       const nsACString &aSQLStatement)
 {
   NS_ASSERTION(aDBConnection, "No database connection given!");
   NS_ASSERTION(!mDBStatement, "Statement already initialized!");
 
   sqlite3 *db = aDBConnection->GetNativeConnection();
   NS_ASSERTION(db, "We should never be called with a null sqlite3 database!");
 
-  int srv = ::sqlite3_prepare_v2(db, PromiseFlatCString(aSQLStatement).get(),
-                                 -1, &mDBStatement, NULL);
+  int srv = moz_sqlite3_prepare_v2(db, PromiseFlatCString(aSQLStatement).get(),
+                                   -1, &mDBStatement, NULL);
   if (srv != SQLITE_OK) {
 #ifdef PR_LOGGING
       PR_LOG(gStorageLog, PR_LOG_ERROR,
              ("Sqlite statement prepare error: %d '%s'", srv,
               ::sqlite3_errmsg(db)));
       PR_LOG(gStorageLog, PR_LOG_ERROR,
              ("Statement was: '%s'", PromiseFlatCString(aSQLStatement).get()));
 #endif
@@ -312,19 +313,19 @@ Statement::getOwner()
 int
 Statement::getAsyncStatement(sqlite3_stmt **_stmt)
 {
   // If we have no statement, we shouldn't be calling this method!
   NS_ASSERTION(mDBStatement != NULL, "We have no statement to clone!");
 
   // If we do not yet have a cached async statement, clone our statement now.
   if (!mAsyncStatement) {
-    int rc = ::sqlite3_prepare_v2(mDBConnection->GetNativeConnection(),
-                                  ::sqlite3_sql(mDBStatement), -1,
-                                  &mAsyncStatement, NULL);
+    int rc = moz_sqlite3_prepare_v2(mDBConnection->GetNativeConnection(),
+                                    ::sqlite3_sql(mDBStatement), -1,
+                                    &mAsyncStatement, NULL);
     if (rc != SQLITE_OK) {
       *_stmt = nsnull;
       return rc;
     }
 
 #ifdef PR_LOGGING
     PR_LOG(gStorageLog, PR_LOG_NOTICE,
            ("Cloned statement 0x%p to 0x%p", mDBStatement, mAsyncStatement));
@@ -605,17 +606,17 @@ Statement::ExecuteStep(PRBool *_moreResu
       PRInt32 srv;
       (void)error->GetResult(&srv);
       return convertResultCode(srv);
     }
 
     // We have bound, so now we can clear our array.
     mParamsArray = nsnull;
   }
-  int srv = ::sqlite3_step(mDBStatement);
+  int srv = moz_sqlite3_step(mDBStatement);
 
 #ifdef PR_LOGGING
   if (srv != SQLITE_ROW && srv != SQLITE_DONE) {
       nsCAutoString errStr;
       (void)mDBConnection->GetLastErrorString(errStr);
       PR_LOG(gStorageLog, PR_LOG_DEBUG,
              ("Statement::ExecuteStep error: %s", errStr.get()));
   }