Bug 1900093 - Add OPEN_NOT_EXCLUSIVE option for opening sqlite database. r=mak
Differential Revision: https://phabricator.services.mozilla.com/D212466
This commit is contained in:
@@ -75,6 +75,15 @@ interface mozIStorageService : nsISupports {
|
||||
*/
|
||||
const unsigned long OPEN_IGNORE_LOCKING_MODE = 1 << 2;
|
||||
|
||||
/**
|
||||
* Allow multi-process access to the database file.
|
||||
* Normally this option is disabled as exclusive locking performs better
|
||||
* and provides some protection against third party manipulation of hot
|
||||
* databases. Note however this option only shows its effects on Unix
|
||||
* systems because exclusive locking is not yet implemented on Windows.
|
||||
*/
|
||||
const unsigned long OPEN_NOT_EXCLUSIVE = 1 << 3;
|
||||
|
||||
/**
|
||||
* All optional connection object features are off.
|
||||
*/
|
||||
@@ -121,8 +130,7 @@ interface mozIStorageService : nsISupports {
|
||||
*
|
||||
* @param aOpenFlags
|
||||
* A set of flags to open the database with optional features.
|
||||
* Currently supports OPEN_SHARED, OPEN_READONLY and
|
||||
* OPEN_IGNORE_LOCKING_MODE flags.
|
||||
* See OPEN_* options above.
|
||||
* For full details, please refer to the documentation of the flags.
|
||||
*
|
||||
* @param aConnectionFlags
|
||||
|
||||
@@ -785,7 +785,7 @@ NS_IMPL_ISUPPORTS_INHERITED(AsyncBackupDatabaseFile, Runnable, nsITimerCallback)
|
||||
Connection::Connection(Service* aService, int aFlags,
|
||||
ConnectionOperation aSupportedOperations,
|
||||
const nsCString& aTelemetryFilename, bool aInterruptible,
|
||||
bool aIgnoreLockingMode)
|
||||
bool aIgnoreLockingMode, bool aOpenNotExclusive)
|
||||
: sharedAsyncExecutionMutex("Connection::sharedAsyncExecutionMutex"),
|
||||
sharedDBMutex("Connection::sharedDBMutex"),
|
||||
eventTargetOpenedOn(WrapNotNull(GetCurrentSerialEventTarget())),
|
||||
@@ -801,6 +801,7 @@ Connection::Connection(Service* aService, int aFlags,
|
||||
mInterruptible(aSupportedOperations == Connection::ASYNCHRONOUS ||
|
||||
aInterruptible),
|
||||
mIgnoreLockingMode(aIgnoreLockingMode),
|
||||
mOpenNotExclusive(aOpenNotExclusive),
|
||||
mAsyncExecutionThreadShuttingDown(false),
|
||||
mConnectionClosed(false),
|
||||
mGrowthChunkSize(0) {
|
||||
@@ -1086,7 +1087,8 @@ nsresult Connection::initialize(nsIFile* aDatabaseFile) {
|
||||
nsresult rv = aDatabaseFile->GetPath(path);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
bool exclusive = StaticPrefs::storage_sqlite_exclusiveLock_enabled();
|
||||
bool exclusive =
|
||||
StaticPrefs::storage_sqlite_exclusiveLock_enabled() && !mOpenNotExclusive;
|
||||
int srv;
|
||||
if (mIgnoreLockingMode) {
|
||||
exclusive = false;
|
||||
@@ -1170,7 +1172,8 @@ nsresult Connection::initialize(nsIFileURL* aFileURL) {
|
||||
return true;
|
||||
}));
|
||||
|
||||
bool exclusive = StaticPrefs::storage_sqlite_exclusiveLock_enabled();
|
||||
bool exclusive =
|
||||
StaticPrefs::storage_sqlite_exclusiveLock_enabled() && !mOpenNotExclusive;
|
||||
|
||||
const char* const vfs = hasKey ? obfsvfs::GetVFSName()
|
||||
: hasDirectoryLockId ? quotavfs::GetVFSName()
|
||||
@@ -1927,7 +1930,8 @@ Connection::AsyncClone(bool aReadOnly,
|
||||
// The cloned connection will still implement the synchronous API, but throw
|
||||
// if any synchronous methods are called on the main thread.
|
||||
RefPtr<Connection> clone =
|
||||
new Connection(mStorageService, flags, ASYNCHRONOUS, mTelemetryFilename);
|
||||
new Connection(mStorageService, flags, ASYNCHRONOUS, mTelemetryFilename,
|
||||
mInterruptible, mIgnoreLockingMode, mOpenNotExclusive);
|
||||
|
||||
RefPtr<AsyncInitializeClone> initEvent =
|
||||
new AsyncInitializeClone(this, clone, aReadOnly, aCallback);
|
||||
|
||||
@@ -86,7 +86,7 @@ class Connection final : public mozIStorageConnection,
|
||||
Connection(Service* aService, int aFlags,
|
||||
ConnectionOperation aSupportedOperations,
|
||||
const nsCString& aTelemetryFilename, bool aInterruptible = false,
|
||||
bool aIgnoreLockingMode = false);
|
||||
bool aIgnoreLockingMode = false, bool aOpenNotExclusive = false);
|
||||
|
||||
/**
|
||||
* Creates the connection to an in-memory database.
|
||||
@@ -480,6 +480,12 @@ class Connection final : public mozIStorageConnection,
|
||||
*/
|
||||
const bool mIgnoreLockingMode;
|
||||
|
||||
/**
|
||||
* Stores whether we should ask sqlite3_open_v2 to open without an exclusive
|
||||
* lock.
|
||||
*/
|
||||
const bool mOpenNotExclusive;
|
||||
|
||||
/**
|
||||
* Set to true by Close() or AsyncClose() prior to shutdown.
|
||||
*
|
||||
|
||||
@@ -547,6 +547,8 @@ Service::OpenAsyncDatabase(nsIVariant* aDatabaseStore, uint32_t aOpenFlags,
|
||||
// Specifying ignoreLockingMode will force use of the readOnly flag:
|
||||
const bool readOnly =
|
||||
ignoreLockingMode || (aOpenFlags & mozIStorageService::OPEN_READONLY);
|
||||
const bool openNotExclusive =
|
||||
aOpenFlags & mozIStorageService::OPEN_NOT_EXCLUSIVE;
|
||||
int flags = readOnly ? SQLITE_OPEN_READONLY : SQLITE_OPEN_READWRITE;
|
||||
|
||||
nsCOMPtr<nsIFile> storageFile;
|
||||
@@ -591,9 +593,9 @@ Service::OpenAsyncDatabase(nsIVariant* aDatabaseStore, uint32_t aOpenFlags,
|
||||
rv = storageFile->GetNativeLeafName(telemetryFilename);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
RefPtr<Connection> msc =
|
||||
new Connection(this, flags, Connection::ASYNCHRONOUS, telemetryFilename,
|
||||
/* interruptible */ true, ignoreLockingMode);
|
||||
RefPtr<Connection> msc = new Connection(
|
||||
this, flags, Connection::ASYNCHRONOUS, telemetryFilename,
|
||||
/* interruptible */ true, ignoreLockingMode, openNotExclusive);
|
||||
nsCOMPtr<nsIEventTarget> target = msc->getAsyncExecutionTarget();
|
||||
MOZ_ASSERT(target,
|
||||
"Cannot initialize a connection that has been closed already");
|
||||
|
||||
@@ -1247,6 +1247,9 @@ ConnectionData.prototype = Object.freeze({
|
||||
* return "false positive" corruption errors if other connections write
|
||||
* to the DB at the same time.
|
||||
*
|
||||
* openNotExclusive -- (bool) Whether to open the database without an exclusive
|
||||
* lock so the database can be accessed from multiple processes.
|
||||
*
|
||||
* vacuumOnIdle -- (bool) Whether to register this connection to be vacuumed
|
||||
* on idle by the VacuumManager component.
|
||||
* If you're vacuum-ing an incremental vacuum database, ensure to also
|
||||
@@ -1384,6 +1387,9 @@ function openConnection(options) {
|
||||
dbOpenOptions |= Ci.mozIStorageService.OPEN_IGNORE_LOCKING_MODE;
|
||||
dbOpenOptions |= Ci.mozIStorageService.OPEN_READONLY;
|
||||
}
|
||||
if (options.openNotExclusive) {
|
||||
dbOpenOptions |= Ci.mozIStorageService.OPEN_NOT_EXCLUSIVE;
|
||||
}
|
||||
|
||||
let dbConnectionOptions = Ci.mozIStorageService.CONNECTION_DEFAULT;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user