forked from mirrors/gecko-dev
Bug 1676573 - Add support for named in-memory databases; r=asuth,dom-workers-and-storage-reviewers
Naming in-memory databases also allows cloning which is the primary goal of this patch. Differential Revision: https://phabricator.services.mozilla.com/D96527
This commit is contained in:
parent
cf7e7e302d
commit
774bada3e2
6 changed files with 50 additions and 23 deletions
|
|
@ -752,7 +752,9 @@ nsresult PermissionManager::OpenDatabase(nsIFile* aPermissionsFile) {
|
|||
}
|
||||
// cache a connection to the hosts database
|
||||
if (mMemoryOnlyDB) {
|
||||
rv = storage->OpenSpecialDatabase("memory", getter_AddRefs(data->mDBConn));
|
||||
rv =
|
||||
storage->OpenSpecialDatabase(kMozStorageMemoryStorageKey, VoidCString(),
|
||||
getter_AddRefs(data->mDBConn));
|
||||
} else {
|
||||
rv = storage->OpenDatabase(aPermissionsFile, getter_AddRefs(data->mDBConn));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -78,6 +78,14 @@ interface mozIStorageService : nsISupports {
|
|||
* @param aStorageKey a string key identifying the type of storage
|
||||
* requested. Valid values include: "memory".
|
||||
*
|
||||
* @param aName an optional string identifying the name of the database.
|
||||
* If omitted, a filename of ":memory:" will be used which results in a
|
||||
* private in-memory database specific to this connection, making it
|
||||
* impossible to clone the in-memory database. If you want to be able to
|
||||
* clone the connection (or otherwise connect to the in-memory database from
|
||||
* a connection), then you must pick a name that's sufficiently unique within
|
||||
* the process to not collide with other mozStorage users.
|
||||
*
|
||||
* @see openDatabase for restrictions on how database connections may be
|
||||
* used. For the profile database, you should only access it from the main
|
||||
* thread since other callers may also have connections.
|
||||
|
|
@ -87,7 +95,8 @@ interface mozIStorageService : nsISupports {
|
|||
*
|
||||
* @throws NS_ERROR_INVALID_ARG if aStorageKey is invalid.
|
||||
*/
|
||||
mozIStorageConnection openSpecialDatabase(in string aStorageKey);
|
||||
mozIStorageConnection openSpecialDatabase(in ACString aStorageKey,
|
||||
[optional] in ACString aName);
|
||||
|
||||
/**
|
||||
* Open a connection to the specified file.
|
||||
|
|
@ -192,6 +201,6 @@ interface mozIStorageService : nsISupports {
|
|||
|
||||
%{C++
|
||||
|
||||
#define MOZ_STORAGE_MEMORY_STORAGE_KEY "memory"
|
||||
constexpr auto kMozStorageMemoryStorageKey = "memory"_ns;
|
||||
|
||||
%}
|
||||
|
|
|
|||
|
|
@ -660,16 +660,26 @@ void Connection::RecordQueryStatus(int srv) {
|
|||
}
|
||||
}
|
||||
|
||||
nsresult Connection::initialize() {
|
||||
nsresult Connection::initialize(const nsACString& aStorageKey,
|
||||
const nsACString& aName) {
|
||||
MOZ_ASSERT(aStorageKey.Equals(kMozStorageMemoryStorageKey));
|
||||
NS_ASSERTION(!connectionReady(),
|
||||
"Initialize called on already opened database!");
|
||||
MOZ_ASSERT(!mIgnoreLockingMode, "Can't ignore locking on an in-memory db.");
|
||||
AUTO_PROFILER_LABEL("Connection::initialize", OTHER);
|
||||
|
||||
mTelemetryFilename.AssignLiteral(":memory:");
|
||||
mStorageKey = aStorageKey;
|
||||
mName = aName;
|
||||
|
||||
// in memory database requested, sqlite uses a magic file name
|
||||
int srv = ::sqlite3_open_v2(":memory:", &mDBConn, mFlags,
|
||||
|
||||
const nsAutoCString path = mName.IsEmpty()
|
||||
? nsAutoCString(":memory:"_ns)
|
||||
: "file:"_ns + mName + "?mode=memory"_ns;
|
||||
|
||||
mTelemetryFilename.AssignLiteral(":memory:");
|
||||
|
||||
int srv = ::sqlite3_open_v2(path.get(), &mDBConn, mFlags,
|
||||
GetTelemetryVFSName(true));
|
||||
if (srv != SQLITE_OK) {
|
||||
mDBConn = nullptr;
|
||||
|
|
@ -903,7 +913,9 @@ nsresult Connection::initializeInternal() {
|
|||
|
||||
nsresult Connection::initializeOnAsyncThread(nsIFile* aStorageFile) {
|
||||
MOZ_ASSERT(threadOpenedOn != NS_GetCurrentThread());
|
||||
nsresult rv = aStorageFile ? initialize(aStorageFile) : initialize();
|
||||
nsresult rv = aStorageFile
|
||||
? initialize(aStorageFile)
|
||||
: initialize(kMozStorageMemoryStorageKey, VoidCString());
|
||||
if (NS_FAILED(rv)) {
|
||||
// Shutdown the async thread, since initialization failed.
|
||||
MutexAutoLock lockedScope(sharedAsyncExecutionMutex);
|
||||
|
|
@ -1568,8 +1580,14 @@ Connection::AsyncClone(bool aReadOnly,
|
|||
}
|
||||
|
||||
nsresult Connection::initializeClone(Connection* aClone, bool aReadOnly) {
|
||||
nsresult rv = mFileURL ? aClone->initialize(mFileURL, mTelemetryFilename)
|
||||
: aClone->initialize(mDatabaseFile);
|
||||
nsresult rv;
|
||||
if (!mStorageKey.IsEmpty()) {
|
||||
rv = aClone->initialize(mStorageKey, mName);
|
||||
} else if (mFileURL) {
|
||||
rv = aClone->initialize(mFileURL, mTelemetryFilename);
|
||||
} else {
|
||||
rv = aClone->initialize(mDatabaseFile);
|
||||
}
|
||||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
|
|
@ -1703,7 +1721,6 @@ Connection::Clone(bool aReadOnly, mozIStorageConnection** _connection) {
|
|||
if (NS_FAILED(rv)) {
|
||||
return rv;
|
||||
}
|
||||
if (!mDatabaseFile) return NS_ERROR_UNEXPECTED;
|
||||
|
||||
int flags = mFlags;
|
||||
if (aReadOnly) {
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ class Connection final : public mozIStorageConnection,
|
|||
/**
|
||||
* Creates the connection to an in-memory database.
|
||||
*/
|
||||
nsresult initialize();
|
||||
nsresult initialize(const nsACString& aStorageKey, const nsACString& aName);
|
||||
|
||||
/**
|
||||
* Creates the connection to the database.
|
||||
|
|
@ -380,6 +380,8 @@ class Connection final : public mozIStorageConnection,
|
|||
nsresult ensureOperationSupported(ConnectionOperation aOperationType);
|
||||
|
||||
sqlite3* mDBConn;
|
||||
nsCString mStorageKey;
|
||||
nsCString mName;
|
||||
nsCOMPtr<nsIFileURL> mFileURL;
|
||||
nsCOMPtr<nsIFile> mDatabaseFile;
|
||||
|
||||
|
|
|
|||
|
|
@ -401,22 +401,18 @@ nsICollation* Service::getLocaleCollation() {
|
|||
//// mozIStorageService
|
||||
|
||||
NS_IMETHODIMP
|
||||
Service::OpenSpecialDatabase(const char* aStorageKey,
|
||||
Service::OpenSpecialDatabase(const nsACString& aStorageKey,
|
||||
const nsACString& aName,
|
||||
mozIStorageConnection** _connection) {
|
||||
nsresult rv;
|
||||
|
||||
nsCOMPtr<nsIFile> storageFile;
|
||||
if (::strcmp(aStorageKey, "memory") == 0) {
|
||||
// just fall through with nullptr storageFile, this will cause the storage
|
||||
// connection to use a memory DB.
|
||||
} else {
|
||||
if (!aStorageKey.Equals(kMozStorageMemoryStorageKey)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
RefPtr<Connection> msc =
|
||||
new Connection(this, SQLITE_OPEN_READWRITE, Connection::SYNCHRONOUS);
|
||||
new Connection(this, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
|
||||
Connection::SYNCHRONOUS);
|
||||
|
||||
rv = storageFile ? msc->initialize(storageFile) : msc->initialize();
|
||||
nsresult rv = msc->initialize(aStorageKey, aName);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
msc.forget(_connection);
|
||||
|
|
@ -550,7 +546,7 @@ Service::OpenAsyncDatabase(nsIVariant* aDatabaseStore,
|
|||
// Sometimes, however, it's a special database name.
|
||||
nsAutoCString keyString;
|
||||
rv = aDatabaseStore->GetAsACString(keyString);
|
||||
if (NS_FAILED(rv) || !keyString.EqualsLiteral("memory")) {
|
||||
if (NS_FAILED(rv) || !keyString.Equals(kMozStorageMemoryStorageKey)) {
|
||||
return NS_ERROR_INVALID_ARG;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -54,7 +54,8 @@ already_AddRefed<mozIStorageService> getService() {
|
|||
already_AddRefed<mozIStorageConnection> getMemoryDatabase() {
|
||||
nsCOMPtr<mozIStorageService> ss = getService();
|
||||
nsCOMPtr<mozIStorageConnection> conn;
|
||||
nsresult rv = ss->OpenSpecialDatabase("memory", getter_AddRefs(conn));
|
||||
nsresult rv = ss->OpenSpecialDatabase(kMozStorageMemoryStorageKey,
|
||||
VoidCString(), getter_AddRefs(conn));
|
||||
do_check_success(rv);
|
||||
return conn.forget();
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue