Bug 519769 - Open shared/unshared connection with options instead of setting shared state always
authorShawn Wilsher <sdwilsh@shawnwilsher.com>
Fri, 27 Aug 2010 12:42:55 -0700
changeset 51597 88be5af389ed77a857a3ad338fed7fcbaaadd628
parent 51596 b6f61845c3dd00a0aec0350f0e2b0c3a61bb568a
child 51598 bc95b9869d3f593d0b4e6e938075c15cd8a5db9c
push idunknown
push userunknown
push dateunknown
bugs519769
milestone2.0b5pre
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 519769 - Open shared/unshared connection with options instead of setting shared state always Use the flags SQLite provides on sqlite3_open_v2 instead of using a mutex to protect the shared cache state. r=asuth a=gavin
storage/src/mozStorageConnection.cpp
storage/src/mozStorageConnection.h
storage/src/mozStorageService.cpp
--- a/storage/src/mozStorageConnection.cpp
+++ b/storage/src/mozStorageConnection.cpp
@@ -348,35 +348,40 @@ Connection::getAsyncExecutionTarget()
       return nsnull;
     }
   }
 
   return mAsyncExecutionThread;
 }
 
 nsresult
-Connection::initialize(nsIFile *aDatabaseFile)
+Connection::initialize(nsIFile *aDatabaseFile,
+                       int aFlags)
 {
   NS_ASSERTION (!mDBConn, "Initialize called on already opened database!");
 
   int srv;
   nsresult rv;
 
   mDatabaseFile = aDatabaseFile;
 
+  // Always ensure that SQLITE_OPEN_CREATE is passed in for compatibility
+  // reasons.
+  int flags = aFlags | SQLITE_OPEN_CREATE;
   if (aDatabaseFile) {
     nsAutoString path;
     rv = aDatabaseFile->GetPath(path);
     NS_ENSURE_SUCCESS(rv, rv);
 
-    srv = ::sqlite3_open(NS_ConvertUTF16toUTF8(path).get(), &mDBConn);
+    srv = ::sqlite3_open_v2(NS_ConvertUTF16toUTF8(path).get(), &mDBConn, flags,
+                            NULL);
   }
   else {
     // in memory database requested, sqlite uses a magic file name
-    srv = ::sqlite3_open(":memory:", &mDBConn);
+    srv = ::sqlite3_open_v2(":memory:", &mDBConn, flags, NULL);
   }
   if (srv != SQLITE_OK) {
     mDBConn = nsnull;
     return convertResultCode(srv);
   }
 
   // Properly wrap the database handle's mutex.
   sharedDBMutex.initWithMutex(sqlite3_db_mutex(mDBConn));
--- a/storage/src/mozStorageConnection.h
+++ b/storage/src/mozStorageConnection.h
@@ -74,18 +74,21 @@ public:
 
   /**
    * Creates the connection to the database.
    *
    * @param aDatabaseFile
    *        The nsIFile of the location of the database to open, or create if it
    *        does not exist.  Passing in nsnull here creates an in-memory
    *        database.
+   * @param aFlags
+   *        The flags to pass to sqlite3_open_v2.  For compatibility reasons,
+   *        We always pass SQLITE_OPEN_CREATE to sqlite3_open_v2.
    */
-  nsresult initialize(nsIFile *aDatabaseFile);
+  nsresult initialize(nsIFile *aDatabaseFile, int aFlags);
 
   // fetch the native handle
   sqlite3 *GetNativeConnection() { return mDBConn; }
 
   /**
    * Lazily creates and returns a background execution thread.  In the future,
    * the thread may be re-claimed if left idle, so you should call this
    * method just before you dispatch and not save the reference.
--- a/storage/src/mozStorageService.cpp
+++ b/storage/src/mozStorageService.cpp
@@ -243,25 +243,16 @@ Service::initialize()
 
   // Explicitly initialize sqlite3.  Although this is implicitly called by
   // various sqlite3 functions (and the sqlite3_open calls in our case),
   // the documentation suggests calling this directly.  So we do.
   rc = ::sqlite3_initialize();
   if (rc != SQLITE_OK)
     return convertResultCode(rc);
 
-  // This makes multiple connections to the same database share the same pager
-  // cache.  We do not need to lock here with mMutex because this function is
-  // only ever called from Service::GetSingleton, which will only
-  // call this function once, and will not return until this function returns.
-  // (It does not matter where this is called relative to sqlite3_initialize.)
-  rc = ::sqlite3_enable_shared_cache(1);
-  if (rc != SQLITE_OK)
-    return convertResultCode(rc);
-
   // Run the things that need to run on the main thread there.
   nsCOMPtr<nsIRunnable> event =
     new ServiceMainThreadInitializer(this, &sXPConnect);
   if (event && ::NS_IsMainThread()) {
     (void)event->Run();
   }
   else {
     (void)::NS_DispatchToMainThread(event);
@@ -364,17 +355,17 @@ Service::OpenSpecialDatabase(const char 
   }
   else {
     return NS_ERROR_INVALID_ARG;
   }
 
   Connection *msc = new Connection(this);
   NS_ENSURE_TRUE(msc, NS_ERROR_OUT_OF_MEMORY);
 
-  rv = msc->initialize(storageFile);
+  rv = msc->initialize(storageFile, SQLITE_OPEN_READWRITE);
   NS_ENSURE_SUCCESS(rv, rv);
 
   NS_ADDREF(*_connection = msc);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 Service::OpenDatabase(nsIFile *aDatabaseFile,
@@ -386,21 +377,19 @@ Service::OpenDatabase(nsIFile *aDatabase
   nsCString leafname;
   (void)aDatabaseFile->GetNativeLeafName(leafname);
   NS_TIME_FUNCTION_FMT("mozIStorageService::OpenDatabase(%s)", leafname.get());
 #endif
 
   nsRefPtr<Connection> msc = new Connection(this);
   NS_ENSURE_TRUE(msc, NS_ERROR_OUT_OF_MEMORY);
 
-  {
-    MutexAutoLock mutex(mMutex);
-    nsresult rv = msc->initialize(aDatabaseFile);
-    NS_ENSURE_SUCCESS(rv, rv);
-  }
+  int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_SHAREDCACHE;
+  nsresult rv = msc->initialize(aDatabaseFile, flags);
+  NS_ENSURE_SUCCESS(rv, rv);
 
   NS_ADDREF(*_connection = msc);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 Service::OpenUnsharedDatabase(nsIFile *aDatabaseFile,
                               mozIStorageConnection **_connection)
@@ -410,35 +399,18 @@ Service::OpenUnsharedDatabase(nsIFile *a
   (void)aDatabaseFile->GetNativeLeafName(leafname);
   NS_TIME_FUNCTION_FMT("mozIStorageService::OpenUnsharedDatabase(%s)",
                        leafname.get());
 #endif
 
   nsRefPtr<Connection> msc = new Connection(this);
   NS_ENSURE_TRUE(msc, NS_ERROR_OUT_OF_MEMORY);
 
-  // Initialize the connection, temporarily turning off shared caches so the
-  // new connection gets its own cache.  Database connections are assigned
-  // caches when they are opened, and they retain those caches for their
-  // lifetimes, unaffected by changes to the shared caches setting, so we can
-  // disable shared caches temporarily while we initialize the new connection
-  // without affecting the caches currently in use by other connections.
-  nsresult rv;
-  {
-    MutexAutoLock mutex(mMutex);
-    int rc = ::sqlite3_enable_shared_cache(0);
-    if (rc != SQLITE_OK)
-      return convertResultCode(rc);
-
-    rv = msc->initialize(aDatabaseFile);
-
-    rc = ::sqlite3_enable_shared_cache(1);
-    if (rc != SQLITE_OK)
-      return convertResultCode(rc);
-  }
+  int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_PRIVATECACHE;
+  nsresult rv = msc->initialize(aDatabaseFile, flags);
   NS_ENSURE_SUCCESS(rv, rv);
 
   NS_ADDREF(*_connection = msc);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 Service::BackupDatabaseFile(nsIFile *aDBFile,