diff --git a/db/sqlite3/src/sqlite.def b/db/sqlite3/src/sqlite.def index bcaf4ed374c..3aa5775b90d 100644 --- a/db/sqlite3/src/sqlite.def +++ b/db/sqlite3/src/sqlite.def @@ -83,7 +83,6 @@ EXPORTS sqlite3_create_module sqlite3_data_count sqlite3_db_handle - sqlite3_db_mutex sqlite3_declare_vtab sqlite3_enable_load_extension sqlite3_enable_shared_cache diff --git a/storage/src/mozStorageConnection.cpp b/storage/src/mozStorageConnection.cpp index deecbc23011..29c3e23d055 100644 --- a/storage/src/mozStorageConnection.cpp +++ b/storage/src/mozStorageConnection.cpp @@ -249,8 +249,10 @@ Connection::Connection(Service *aService) , mDBConn(nsnull) , mAsyncExecutionMutex(nsAutoLock::NewLock("AsyncExecutionMutex")) , mAsyncExecutionThreadShuttingDown(PR_FALSE) -, mDBMutex("Connection::mDBMutex") +, mTransactionMutex(nsAutoLock::NewLock("TransactionMutex")) , mTransactionInProgress(PR_FALSE) +, mFunctionsMutex(nsAutoLock::NewLock("FunctionsMutex")) +, mProgressHandlerMutex(nsAutoLock::NewLock("ProgressHandlerMutex")) , mProgressHandler(nsnull) , mStorageService(aService) { @@ -261,6 +263,9 @@ Connection::~Connection() { (void)Close(); nsAutoLock::DestroyLock(mAsyncExecutionMutex); + nsAutoLock::DestroyLock(mTransactionMutex); + nsAutoLock::DestroyLock(mFunctionsMutex); + nsAutoLock::DestroyLock(mProgressHandlerMutex); } NS_IMPL_THREADSAFE_ISUPPORTS1( @@ -296,6 +301,9 @@ Connection::initialize(nsIFile *aDatabaseFile) { NS_ASSERTION (!mDBConn, "Initialize called on already opened database!"); NS_ENSURE_TRUE(mAsyncExecutionMutex, NS_ERROR_OUT_OF_MEMORY); + NS_ENSURE_TRUE(mTransactionMutex, NS_ERROR_OUT_OF_MEMORY); + NS_ENSURE_TRUE(mFunctionsMutex, NS_ERROR_OUT_OF_MEMORY); + NS_ENSURE_TRUE(mProgressHandlerMutex, NS_ERROR_OUT_OF_MEMORY); int srv; nsresult rv; @@ -318,9 +326,6 @@ Connection::initialize(nsIFile *aDatabaseFile) return convertResultCode(srv); } - // Properly wrap the database handle's mutex. - mDBMutex.initWithMutex(sqlite3_db_mutex(mDBConn)); - #ifdef PR_LOGGING if (!gStorageLog) gStorageLog = ::PR_NewLogModule("mozStorage"); @@ -439,7 +444,7 @@ Connection::databaseElementExists(enum DatabaseElementType aElementType, bool Connection::findFunctionByInstance(nsISupports *aInstance) { - mDBMutex.assertCurrentThreadOwns(); + PR_ASSERT_CURRENT_THREAD_OWNS_LOCK(mFunctionsMutex); FFEArguments args = { aInstance, false }; mFunctions.EnumerateRead(findFunctionEnumerator, &args); return args.found; @@ -455,7 +460,7 @@ Connection::sProgressHelper(void *aArg) int Connection::progressHandler() { - mDBMutex.assertCurrentThreadOwns(); + nsAutoLock mutex(mProgressHandlerMutex); if (mProgressHandler) { PRBool result; nsresult rv = mProgressHandler->OnProgress(this, &result); @@ -507,6 +512,12 @@ Connection::Close() } #endif + { + nsAutoLock mutex(mProgressHandlerMutex); + if (mProgressHandler) + ::sqlite3_progress_handler(mDBConn, 0, NULL, NULL); + } + int srv = ::sqlite3_close(mDBConn); NS_ASSERTION(srv == SQLITE_OK, "sqlite3_close failed. There are probably outstanding statements that are listed above!"); @@ -630,45 +641,42 @@ Connection::ExecuteAsync(mozIStorageStatement **aStatements, { int rc = SQLITE_OK; nsTArray stmts(aNumStatements); - { - SQLiteMutexAutoLock lockedScope(mDBMutex); - for (PRUint32 i = 0; i < aNumStatements && rc == SQLITE_OK; i++) { - sqlite3_stmt *old_stmt = - static_cast(aStatements[i])->nativeStatement(); - if (!old_stmt) { - rc = SQLITE_MISUSE; - break; - } - NS_ASSERTION(::sqlite3_db_handle(old_stmt) == mDBConn, - "Statement must be from this database connection!"); + for (PRUint32 i = 0; i < aNumStatements && rc == SQLITE_OK; i++) { + sqlite3_stmt *old_stmt = + static_cast(aStatements[i])->nativeStatement(); + if (!old_stmt) { + rc = SQLITE_MISUSE; + break; + } + NS_ASSERTION(::sqlite3_db_handle(old_stmt) == mDBConn, + "Statement must be from this database connection!"); - // Clone this statement. We only need a sqlite3_stmt object, so we can - // avoid all the extra work that making a new Statement would normally - // involve and use the SQLite API. - sqlite3_stmt *new_stmt; - rc = ::sqlite3_prepare_v2(mDBConn, ::sqlite3_sql(old_stmt), -1, &new_stmt, - NULL); - if (rc != SQLITE_OK) - break; + // Clone this statement. We only need a sqlite3_stmt object, so we can + // avoid all the extra work that making a new Statement would normally + // involve and use the SQLite API. + sqlite3_stmt *new_stmt; + rc = ::sqlite3_prepare_v2(mDBConn, ::sqlite3_sql(old_stmt), -1, &new_stmt, + NULL); + if (rc != SQLITE_OK) + break; #ifdef PR_LOGGING - PR_LOG(gStorageLog, PR_LOG_NOTICE, - ("Cloned statement 0x%p to 0x%p", old_stmt, new_stmt)); + PR_LOG(gStorageLog, PR_LOG_NOTICE, + ("Cloned statement 0x%p to 0x%p", old_stmt, new_stmt)); #endif - // Transfer the bindings - rc = sqlite3_transfer_bindings(old_stmt, new_stmt); - if (rc != SQLITE_OK) - break; + // Transfer the bindings + rc = sqlite3_transfer_bindings(old_stmt, new_stmt); + if (rc != SQLITE_OK) + break; - Statement *storageStmt = static_cast(aStatements[i]); - StatementData data(new_stmt, storageStmt->bindingParamsArray()); - if (!stmts.AppendElement(data)) { - rc = SQLITE_NOMEM; - break; - } - } // for loop - } // locked Scope + Statement *storageStmt = static_cast(aStatements[i]); + StatementData data(new_stmt, storageStmt->bindingParamsArray()); + if (!stmts.AppendElement(data)) { + rc = SQLITE_NOMEM; + break; + } + } // Dispatch to the background nsresult rv = NS_OK; @@ -685,11 +693,8 @@ Connection::ExecuteAsync(mozIStorageStatement **aStatements, } // Always reset all the statements - { - SQLiteMutexAutoLock lockedScope(mDBMutex); - for (PRUint32 i = 0; i < aNumStatements; i++) - (void)aStatements[i]->Reset(); - } + for (PRUint32 i = 0; i < aNumStatements; i++) + (void)aStatements[i]->Reset(); return rv; } @@ -711,7 +716,7 @@ Connection::IndexExists(const nsACString &aIndexName, NS_IMETHODIMP Connection::GetTransactionInProgress(PRBool *_inProgress) { - SQLiteMutexAutoLock lockedScope(mDBMutex); + nsAutoLock mutex(mTransactionMutex); *_inProgress = mTransactionInProgress; return NS_OK; } @@ -725,7 +730,7 @@ Connection::BeginTransaction() NS_IMETHODIMP Connection::BeginTransactionAs(PRInt32 aTransactionType) { - SQLiteMutexAutoLock lockedScope(mDBMutex); + nsAutoLock mutex(mTransactionMutex); if (mTransactionInProgress) return NS_ERROR_FAILURE; nsresult rv; @@ -750,7 +755,7 @@ Connection::BeginTransactionAs(PRInt32 aTransactionType) NS_IMETHODIMP Connection::CommitTransaction() { - SQLiteMutexAutoLock lockedScope(mDBMutex); + nsAutoLock mutex(mTransactionMutex); if (!mTransactionInProgress) return NS_ERROR_FAILURE; nsresult rv = ExecuteSimpleSQL(NS_LITERAL_CSTRING("COMMIT TRANSACTION")); @@ -762,7 +767,7 @@ Connection::CommitTransaction() NS_IMETHODIMP Connection::RollbackTransaction() { - SQLiteMutexAutoLock lockedScope(mDBMutex); + nsAutoLock mutex(mTransactionMutex); if (!mTransactionInProgress) return NS_ERROR_FAILURE; nsresult rv = ExecuteSimpleSQL(NS_LITERAL_CSTRING("ROLLBACK TRANSACTION")); @@ -796,7 +801,7 @@ Connection::CreateFunction(const nsACString &aFunctionName, // Check to see if this function is already defined. We only check the name // because a function can be defined with the same body but different names. - SQLiteMutexAutoLock lockedScope(mDBMutex); + nsAutoLock mutex(mFunctionsMutex); NS_ENSURE_FALSE(mFunctions.Get(aFunctionName, NULL), NS_ERROR_FAILURE); int srv = ::sqlite3_create_function(mDBConn, @@ -824,7 +829,7 @@ Connection::CreateAggregateFunction(const nsACString &aFunctionName, if (!mDBConn) return NS_ERROR_NOT_INITIALIZED; // Check to see if this function name is already defined. - SQLiteMutexAutoLock lockedScope(mDBMutex); + nsAutoLock mutex(mFunctionsMutex); NS_ENSURE_FALSE(mFunctions.Get(aFunctionName, NULL), NS_ERROR_FAILURE); // Because aggregate functions depend on state across calls, you cannot have @@ -854,7 +859,7 @@ Connection::RemoveFunction(const nsACString &aFunctionName) { if (!mDBConn) return NS_ERROR_NOT_INITIALIZED; - SQLiteMutexAutoLock lockedScope(mDBMutex); + nsAutoLock mutex(mFunctionsMutex); NS_ENSURE_TRUE(mFunctions.Get(aFunctionName, NULL), NS_ERROR_FAILURE); int srv = ::sqlite3_create_function(mDBConn, @@ -881,7 +886,7 @@ Connection::SetProgressHandler(PRInt32 aGranularity, if (!mDBConn) return NS_ERROR_NOT_INITIALIZED; // Return previous one - SQLiteMutexAutoLock lockedScope(mDBMutex); + nsAutoLock mutex(mProgressHandlerMutex); NS_IF_ADDREF(*_oldHandler = mProgressHandler); if (!aHandler || aGranularity <= 0) { @@ -900,7 +905,7 @@ Connection::RemoveProgressHandler(mozIStorageProgressHandler **_oldHandler) if (!mDBConn) return NS_ERROR_NOT_INITIALIZED; // Return previous one - SQLiteMutexAutoLock lockedScope(mDBMutex); + nsAutoLock mutex(mProgressHandlerMutex); NS_IF_ADDREF(*_oldHandler = mProgressHandler); mProgressHandler = nsnull; diff --git a/storage/src/mozStorageConnection.h b/storage/src/mozStorageConnection.h index 54a6598d1b9..c47bd90905b 100644 --- a/storage/src/mozStorageConnection.h +++ b/storage/src/mozStorageConnection.h @@ -48,7 +48,6 @@ #include "nsString.h" #include "nsInterfaceHashtable.h" #include "mozIStorageProgressHandler.h" -#include "SQLiteMutex.h" #include "mozIStorageConnection.h" #include "mozStorageService.h" @@ -159,27 +158,13 @@ private: */ PRBool mAsyncExecutionThreadShuttingDown; - /** - * Wraps the mutex that SQLite gives us from sqlite3_db_mutex. - */ - SQLiteMutex mDBMutex; - - /** - * Tracks if we have a transaction in progress or not. Access protected by - * mDBMutex. - */ + PRLock *mTransactionMutex; PRBool mTransactionInProgress; - /** - * Stores the mapping of a given function by name to its instance. Access is - * protected by mDBMutex. - */ + PRLock *mFunctionsMutex; nsInterfaceHashtable mFunctions; - /** - * Stores the registered progress handler for the database connection. Access - * is protected by mDBMutex. - */ + PRLock *mProgressHandlerMutex; nsCOMPtr mProgressHandler; // This is here for two reasons: 1) It's used to make sure that the