2009-03-31 18:26:16 +04:00
|
|
|
/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
2009-04-13 20:29:41 +04:00
|
|
|
* vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
|
2012-05-21 15:12:37 +04:00
|
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
2004-10-09 04:04:10 +04:00
|
|
|
|
2023-09-26 17:51:38 +03:00
|
|
|
#include "BaseVFS.h"
|
2012-12-15 03:58:45 +04:00
|
|
|
#include "mozilla/Attributes.h"
|
|
|
|
#include "mozilla/DebugOnly.h"
|
2020-11-23 19:10:41 +03:00
|
|
|
#include "mozilla/SpinEventLoopUntil.h"
|
2023-06-24 13:11:28 +03:00
|
|
|
#include "nsIFile.h"
|
|
|
|
#include "nsIFileURL.h"
|
2004-10-09 04:04:10 +04:00
|
|
|
#include "mozStorageService.h"
|
|
|
|
#include "mozStorageConnection.h"
|
Bug 1600545 - Remove useless inclusions of header files generated from IDL files in modules/, netwerk/, parser/, security/, startupcache/, storage/, toolkit/, tools/, uriloader/, widget/, xpcom/ and xpfe/ r=Ehsan
The inclusions were removed with the following very crude script and the
resulting breakage was fixed up by hand. The manual fixups did either
revert the changes done by the script, replace a generic header with a more
specific one or replace a header with a forward declaration.
find . -name "*.idl" | grep -v web-platform | grep -v third_party | while read path; do
interfaces=$(grep "^\(class\|interface\).*:.*" "$path" | cut -d' ' -f2)
if [ -n "$interfaces" ]; then
if [[ "$interfaces" == *$'\n'* ]]; then
regexp="\("
for i in $interfaces; do regexp="$regexp$i\|"; done
regexp="${regexp%%\\\|}\)"
else
regexp="$interfaces"
fi
interface=$(basename "$path")
rg -l "#include.*${interface%%.idl}.h" . | while read path2; do
hits=$(grep -v "#include.*${interface%%.idl}.h" "$path2" | grep -c "$regexp" )
if [ $hits -eq 0 ]; then
echo "Removing ${interface} from ${path2}"
grep -v "#include.*${interface%%.idl}.h" "$path2" > "$path2".tmp
mv -f "$path2".tmp "$path2"
fi
done
fi
done
Differential Revision: https://phabricator.services.mozilla.com/D55444
--HG--
extra : moz-landing-system : lando
2019-12-06 12:17:57 +03:00
|
|
|
#include "nsComponentManagerUtils.h"
|
2008-11-01 03:38:58 +03:00
|
|
|
#include "nsEmbedCID.h"
|
2017-10-20 12:00:21 +03:00
|
|
|
#include "nsExceptionHandler.h"
|
2010-07-24 22:21:17 +04:00
|
|
|
#include "nsThreadUtils.h"
|
2008-10-31 01:50:00 +03:00
|
|
|
#include "mozStoragePrivateHelpers.h"
|
2009-01-22 00:52:16 +03:00
|
|
|
#include "nsIObserverService.h"
|
2013-06-27 17:00:59 +04:00
|
|
|
#include "nsIPropertyBag2.h"
|
2023-09-26 17:51:38 +03:00
|
|
|
#include "ObfuscatingVFS.h"
|
|
|
|
#include "QuotaVFS.h"
|
Bug 560095 - Use mozilla::services::GetObserverService(). r=biesi,dveditz,gavin,josh,jst,mrbkap,roc,sdwilsh,shaver,sicking,smontagu,surkov
2010-04-29 20:59:13 +04:00
|
|
|
#include "mozilla/Services.h"
|
2013-11-05 16:45:20 +04:00
|
|
|
#include "mozilla/LateWriteChecks.h"
|
2013-06-27 17:00:59 +04:00
|
|
|
#include "mozIStorageCompletionCallback.h"
|
2014-03-27 14:19:49 +04:00
|
|
|
#include "mozIStoragePendingStatement.h"
|
2020-10-29 13:13:46 +03:00
|
|
|
#include "mozilla/StaticPrefs_storage.h"
|
2021-08-10 19:01:18 +03:00
|
|
|
#include "mozilla/intl/Collator.h"
|
|
|
|
#include "mozilla/intl/LocaleService.h"
|
2004-10-09 04:04:10 +04:00
|
|
|
|
|
|
|
#include "sqlite3.h"
|
2017-09-29 14:25:06 +03:00
|
|
|
#include "mozilla/AutoSQLiteLifetime.h"
|
2004-10-09 04:04:10 +04:00
|
|
|
|
2017-10-18 14:04:52 +03:00
|
|
|
#ifdef XP_WIN
|
2011-12-16 11:34:24 +04:00
|
|
|
// "windows.h" was included and it can #define lots of things we care about...
|
|
|
|
# undef CompareString
|
|
|
|
#endif
|
|
|
|
|
2021-08-10 19:01:18 +03:00
|
|
|
using mozilla::intl::Collator;
|
|
|
|
|
2023-06-24 13:11:28 +03:00
|
|
|
namespace mozilla::storage {
|
2006-02-16 05:59:42 +03:00
|
|
|
|
2010-07-22 21:08:59 +04:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
//// Memory Reporting
|
|
|
|
|
2013-11-15 17:11:10 +04:00
|
|
|
#ifdef MOZ_DMD
|
2019-01-30 16:00:21 +03:00
|
|
|
mozilla::Atomic<size_t> gSqliteMemoryUsed;
|
2013-11-15 17:11:10 +04:00
|
|
|
#endif
|
|
|
|
|
2013-09-20 02:52:30 +04:00
|
|
|
static int64_t StorageSQLiteDistinguishedAmount() {
|
|
|
|
return ::sqlite3_memory_used();
|
|
|
|
}
|
2010-07-22 21:08:59 +04:00
|
|
|
|
2013-11-07 09:35:30 +04:00
|
|
|
/**
|
|
|
|
* Passes a single SQLite memory statistic to a memory reporter callback.
|
|
|
|
*
|
|
|
|
* @param aHandleReport
|
|
|
|
* The callback.
|
|
|
|
* @param aData
|
|
|
|
* The data for the callback.
|
|
|
|
* @param aConn
|
|
|
|
* The SQLite connection.
|
|
|
|
* @param aPathHead
|
|
|
|
* Head of the path for the memory report.
|
|
|
|
* @param aKind
|
|
|
|
* The memory report statistic kind, one of "stmt", "cache" or
|
|
|
|
* "schema".
|
|
|
|
* @param aDesc
|
|
|
|
* The memory report description.
|
|
|
|
* @param aOption
|
|
|
|
* The SQLite constant for getting the measurement.
|
|
|
|
* @param aTotal
|
|
|
|
* The accumulator for the measurement.
|
|
|
|
*/
|
|
|
|
static void ReportConn(nsIHandleReportCallback* aHandleReport,
|
|
|
|
nsISupports* aData, Connection* aConn,
|
|
|
|
const nsACString& aPathHead, const nsACString& aKind,
|
|
|
|
const nsACString& aDesc, int32_t aOption,
|
|
|
|
size_t* aTotal) {
|
|
|
|
nsCString path(aPathHead);
|
|
|
|
path.Append(aKind);
|
|
|
|
path.AppendLiteral("-used");
|
2012-01-03 12:27:05 +04:00
|
|
|
|
2014-04-24 13:54:09 +04:00
|
|
|
int32_t val = aConn->getSqliteRuntimeStatus(aOption);
|
2020-09-23 18:17:15 +03:00
|
|
|
aHandleReport->Callback(""_ns, path, nsIMemoryReporter::KIND_HEAP,
|
2016-08-24 08:23:45 +03:00
|
|
|
nsIMemoryReporter::UNITS_BYTES, int64_t(val), aDesc,
|
|
|
|
aData);
|
2014-04-24 13:54:09 +04:00
|
|
|
*aTotal += val;
|
2013-11-07 09:35:30 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
// Warning: To get a Connection's measurements requires holding its lock.
|
|
|
|
// There may be a delay getting the lock if another thread is accessing the
|
|
|
|
// Connection. This isn't very nice if CollectReports is called from the main
|
|
|
|
// thread! But at the time of writing this function is only called when
|
|
|
|
// about:memory is loaded (not, for example, when telemetry pings occur) and
|
|
|
|
// any delays in that case aren't so bad.
|
|
|
|
NS_IMETHODIMP
|
|
|
|
Service::CollectReports(nsIHandleReportCallback* aHandleReport,
|
2014-05-21 10:06:54 +04:00
|
|
|
nsISupports* aData, bool aAnonymize) {
|
2013-11-07 09:35:30 +04:00
|
|
|
size_t totalConnSize = 0;
|
2012-01-03 12:27:05 +04:00
|
|
|
{
|
2015-10-18 08:24:48 +03:00
|
|
|
nsTArray<RefPtr<Connection>> connections;
|
2013-11-07 09:35:30 +04:00
|
|
|
getConnections(connections);
|
2013-11-07 09:35:30 +04:00
|
|
|
|
2013-11-07 09:35:30 +04:00
|
|
|
for (uint32_t i = 0; i < connections.Length(); i++) {
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<Connection>& conn = connections[i];
|
2013-11-07 09:35:30 +04:00
|
|
|
|
|
|
|
// Someone may have closed the Connection, in which case we skip it.
|
2017-06-16 18:43:23 +03:00
|
|
|
// Note that we have consumers of the synchronous API that are off the
|
|
|
|
// main-thread, like the DOM Cache and IndexedDB, and as such we must be
|
|
|
|
// sure that we have a connection.
|
|
|
|
MutexAutoLock lockedAsyncScope(conn->sharedAsyncExecutionMutex);
|
2019-04-02 21:49:21 +03:00
|
|
|
if (!conn->connectionReady()) {
|
2013-11-07 09:35:30 +04:00
|
|
|
continue;
|
2013-11-28 05:05:00 +04:00
|
|
|
}
|
2013-11-07 09:35:30 +04:00
|
|
|
|
|
|
|
nsCString pathHead("explicit/storage/sqlite/");
|
2014-05-21 10:06:54 +04:00
|
|
|
// This filename isn't privacy-sensitive, and so is never anonymized.
|
2013-11-07 09:35:30 +04:00
|
|
|
pathHead.Append(conn->getFilename());
|
2014-05-22 07:48:51 +04:00
|
|
|
pathHead.Append('/');
|
2013-11-07 09:35:30 +04:00
|
|
|
|
|
|
|
SQLiteMutexAutoLock lockedScope(conn->sharedDBMutex);
|
|
|
|
|
|
|
|
constexpr auto stmtDesc =
|
|
|
|
"Memory (approximate) used by all prepared statements used by "
|
|
|
|
"connections to this database."_ns;
|
2016-08-24 08:23:45 +03:00
|
|
|
ReportConn(aHandleReport, aData, conn, pathHead, "stmt"_ns, stmtDesc,
|
|
|
|
SQLITE_DBSTATUS_STMT_USED, &totalConnSize);
|
2013-11-07 09:35:30 +04:00
|
|
|
|
|
|
|
constexpr auto cacheDesc =
|
|
|
|
"Memory (approximate) used by all pager caches used by connections "
|
|
|
|
"to this database."_ns;
|
2016-08-24 08:23:45 +03:00
|
|
|
ReportConn(aHandleReport, aData, conn, pathHead, "cache"_ns, cacheDesc,
|
2016-11-04 01:14:35 +03:00
|
|
|
SQLITE_DBSTATUS_CACHE_USED_SHARED, &totalConnSize);
|
2013-11-07 09:35:30 +04:00
|
|
|
|
|
|
|
constexpr auto schemaDesc =
|
|
|
|
"Memory (approximate) used to store the schema for all databases "
|
|
|
|
"associated with connections to this database."_ns;
|
2016-08-24 08:23:45 +03:00
|
|
|
ReportConn(aHandleReport, aData, conn, pathHead, "schema"_ns, schemaDesc,
|
|
|
|
SQLITE_DBSTATUS_SCHEMA_USED, &totalConnSize);
|
2013-11-28 05:05:00 +04:00
|
|
|
}
|
2012-01-03 12:27:05 +04:00
|
|
|
|
2013-11-07 09:35:30 +04:00
|
|
|
#ifdef MOZ_DMD
|
|
|
|
if (::sqlite3_memory_used() != int64_t(gSqliteMemoryUsed)) {
|
|
|
|
NS_WARNING(
|
|
|
|
"memory consumption reported by SQLite doesn't match "
|
|
|
|
"our measurements");
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
2012-01-03 12:27:05 +04:00
|
|
|
|
2023-06-24 13:11:28 +03:00
|
|
|
int64_t other = static_cast<int64_t>(::sqlite3_memory_used() - totalConnSize);
|
2012-01-03 12:27:05 +04:00
|
|
|
|
2016-08-24 08:23:45 +03:00
|
|
|
MOZ_COLLECT_REPORT("explicit/storage/sqlite/other", KIND_HEAP, UNITS_BYTES,
|
|
|
|
other, "All unclassified sqlite memory.");
|
2013-11-28 05:05:00 +04:00
|
|
|
|
2013-11-07 09:35:30 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2012-01-03 12:27:05 +04:00
|
|
|
|
2009-03-31 18:26:16 +04:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
//// Service
|
2007-06-19 06:22:01 +04:00
|
|
|
|
2009-03-31 18:26:16 +04:00
|
|
|
NS_IMPL_ISUPPORTS(Service, mozIStorageService, nsIObserver, nsIMemoryReporter)
|
2008-09-25 22:28:29 +04:00
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
Service* Service::gService = nullptr;
|
2008-11-01 03:38:58 +03:00
|
|
|
|
2017-10-17 07:08:42 +03:00
|
|
|
already_AddRefed<Service> Service::getSingleton() {
|
2009-03-31 18:26:16 +04:00
|
|
|
if (gService) {
|
2017-10-17 07:08:42 +03:00
|
|
|
return do_AddRef(gService);
|
2009-03-31 18:26:16 +04:00
|
|
|
}
|
|
|
|
|
2013-02-08 21:04:26 +04:00
|
|
|
// The first reference to the storage service must be obtained on the
|
|
|
|
// main thread.
|
|
|
|
NS_ENSURE_TRUE(NS_IsMainThread(), nullptr);
|
2017-10-17 07:08:42 +03:00
|
|
|
RefPtr<Service> service = new Service();
|
2017-10-30 02:02:40 +03:00
|
|
|
if (NS_SUCCEEDED(service->initialize())) {
|
|
|
|
// Note: This is cleared in the Service destructor.
|
|
|
|
gService = service.get();
|
|
|
|
return service.forget();
|
2009-03-31 18:26:16 +04:00
|
|
|
}
|
|
|
|
|
2017-10-30 02:02:40 +03:00
|
|
|
return nullptr;
|
2004-10-09 04:04:10 +04:00
|
|
|
}
|
|
|
|
|
2020-10-29 13:13:46 +03:00
|
|
|
int Service::AutoVFSRegistration::Init(UniquePtr<sqlite3_vfs> aVFS) {
|
|
|
|
MOZ_ASSERT(!mVFS);
|
|
|
|
if (aVFS) {
|
|
|
|
mVFS = std::move(aVFS);
|
|
|
|
return sqlite3_vfs_register(mVFS.get(), 0);
|
|
|
|
}
|
|
|
|
NS_WARNING("Failed to register VFS");
|
|
|
|
return SQLITE_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
Service::AutoVFSRegistration::~AutoVFSRegistration() {
|
|
|
|
if (mVFS) {
|
|
|
|
int rc = sqlite3_vfs_unregister(mVFS.get());
|
|
|
|
if (rc != SQLITE_OK) {
|
|
|
|
NS_WARNING("Failed to unregister sqlite vfs wrapper.");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-07-15 21:49:05 +04:00
|
|
|
Service::Service()
|
2013-12-04 08:01:24 +04:00
|
|
|
: mMutex("Service::mMutex"),
|
2011-12-06 03:02:59 +04:00
|
|
|
mRegistrationMutex("Service::mRegistrationMutex"),
|
2023-06-24 13:11:28 +03:00
|
|
|
mLastSensitivity(mozilla::intl::Collator::Sensitivity::Base) {}
|
2009-07-15 21:49:05 +04:00
|
|
|
|
2009-03-31 18:26:16 +04:00
|
|
|
Service::~Service() {
|
2013-11-07 09:35:30 +04:00
|
|
|
mozilla::UnregisterWeakMemoryReporter(this);
|
2013-09-20 02:52:30 +04:00
|
|
|
mozilla::UnregisterStorageSQLiteDistinguishedAmount();
|
2012-01-03 12:27:05 +04:00
|
|
|
|
2012-07-30 18:20:58 +04:00
|
|
|
gService = nullptr;
|
2009-01-22 00:52:16 +03:00
|
|
|
}
|
2008-11-19 09:11:30 +03:00
|
|
|
|
2011-12-06 03:02:59 +04:00
|
|
|
void Service::registerConnection(Connection* aConnection) {
|
|
|
|
mRegistrationMutex.AssertNotCurrentThreadOwns();
|
|
|
|
MutexAutoLock mutex(mRegistrationMutex);
|
|
|
|
(void)mConnections.AppendElement(aConnection);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Service::unregisterConnection(Connection* aConnection) {
|
|
|
|
// If this is the last Connection it might be the only thing keeping Service
|
|
|
|
// alive. So ensure that Service is destroyed only after the Connection is
|
|
|
|
// cleanly unregistered and destroyed.
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<Service> kungFuDeathGrip(this);
|
2017-10-03 08:14:22 +03:00
|
|
|
RefPtr<Connection> forgettingRef;
|
2011-12-06 03:02:59 +04:00
|
|
|
{
|
|
|
|
mRegistrationMutex.AssertNotCurrentThreadOwns();
|
|
|
|
MutexAutoLock mutex(mRegistrationMutex);
|
2015-04-17 05:12:36 +03:00
|
|
|
|
|
|
|
for (uint32_t i = 0; i < mConnections.Length(); ++i) {
|
|
|
|
if (mConnections[i] == aConnection) {
|
2017-10-03 08:14:22 +03:00
|
|
|
// Because dropping the final reference can potentially result in
|
|
|
|
// spinning a nested event loop if the connection was not properly
|
|
|
|
// shutdown, we want to do that outside this loop so that we can finish
|
|
|
|
// mutating the array and drop our mutex.
|
2020-02-13 17:38:48 +03:00
|
|
|
forgettingRef = std::move(mConnections[i]);
|
2015-04-17 05:12:36 +03:00
|
|
|
mConnections.RemoveElementAt(i);
|
2017-10-03 08:14:22 +03:00
|
|
|
break;
|
2015-04-17 05:12:36 +03:00
|
|
|
}
|
|
|
|
}
|
2011-12-06 03:02:59 +04:00
|
|
|
}
|
2017-10-03 08:14:22 +03:00
|
|
|
|
|
|
|
MOZ_ASSERT(forgettingRef,
|
|
|
|
"Attempt to unregister unknown storage connection!");
|
|
|
|
|
2022-09-21 18:02:14 +03:00
|
|
|
// Do not proxy the release anywhere, just let this reference drop here. (We
|
2018-02-26 07:50:42 +03:00
|
|
|
// previously did proxy the release, but that was because we invoked Close()
|
|
|
|
// in the destructor and Close() likes to complain if it's not invoked on the
|
2022-09-21 18:02:14 +03:00
|
|
|
// opener event target, so it was essential that the last reference be dropped
|
|
|
|
// on the opener event target. We now enqueue Close() inside our caller,
|
|
|
|
// Release(), so it doesn't actually matter what thread our reference drops
|
|
|
|
// on.)
|
2011-12-06 03:02:59 +04:00
|
|
|
}
|
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
void Service::getConnections(
|
|
|
|
/* inout */ nsTArray<RefPtr<Connection>>& aConnections) {
|
2011-12-06 03:02:59 +04:00
|
|
|
mRegistrationMutex.AssertNotCurrentThreadOwns();
|
|
|
|
MutexAutoLock mutex(mRegistrationMutex);
|
|
|
|
aConnections.Clear();
|
|
|
|
aConnections.AppendElements(mConnections);
|
|
|
|
}
|
|
|
|
|
2014-03-27 14:19:49 +04:00
|
|
|
void Service::minimizeMemory() {
|
2015-10-18 08:24:48 +03:00
|
|
|
nsTArray<RefPtr<Connection>> connections;
|
2014-03-27 14:19:49 +04:00
|
|
|
getConnections(connections);
|
|
|
|
|
|
|
|
for (uint32_t i = 0; i < connections.Length(); i++) {
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<Connection> conn = connections[i];
|
2017-06-16 18:43:23 +03:00
|
|
|
// For non-main-thread owning/opening threads, we may be racing against them
|
|
|
|
// closing their connection or their thread. That's okay, see below.
|
2019-04-02 21:49:21 +03:00
|
|
|
if (!conn->connectionReady()) {
|
Bug 1482608 - Add basic Rust bindings for mozStorage. r=nika,asuth,mak
This commit wraps just enough of the mozStorage API to support the
bookmarks mirror. It's not complete: for example, there's no way
to open, clone, or close a connection, because the mirror handles
that from JS. The wrapper also omits shutdown blocking and retrying on
`SQLITE_BUSY`.
This commit also changes the behavior of sync and async mozStorage
connections. Async (`mozIStorageAsyncConnection`) methods may be called
from any thread on any connection. Sync (`mozIStorageConnection`)
methods may be called from any thread on a sync connection, and from
background threads on an async connection. All connections now QI
to `mozIStorageConnection`, but attempting to call a sync method on
an async connection from the main thread throws.
Finally, this commit exposes an `OpenedConnection::unsafeRawConnection`
getter in Sqlite.jsm, for JS code to access the underlying connection.
Differential Revision: https://phabricator.services.mozilla.com/D20073
--HG--
extra : moz-landing-system : lando
2019-03-25 07:49:18 +03:00
|
|
|
continue;
|
|
|
|
}
|
2015-01-28 02:00:23 +03:00
|
|
|
|
|
|
|
constexpr auto shrinkPragma = "PRAGMA shrink_memory"_ns;
|
|
|
|
|
2019-04-02 21:49:21 +03:00
|
|
|
if (!conn->operationSupported(Connection::SYNCHRONOUS)) {
|
2015-01-28 02:00:23 +03:00
|
|
|
// This is a mozIStorageAsyncConnection, it can only be used on the main
|
|
|
|
// thread, so we can do a straight API call.
|
|
|
|
nsCOMPtr<mozIStoragePendingStatement> ps;
|
|
|
|
DebugOnly<nsresult> rv = conn->ExecuteSimpleSQLAsync(
|
|
|
|
shrinkPragma, nullptr, getter_AddRefs(ps));
|
|
|
|
MOZ_ASSERT(NS_SUCCEEDED(rv), "Should have purged sqlite caches");
|
2022-09-21 18:02:14 +03:00
|
|
|
} else if (IsOnCurrentSerialEventTarget(conn->eventTargetOpenedOn)) {
|
2017-06-02 00:46:53 +03:00
|
|
|
if (conn->isAsyncExecutionThreadAvailable()) {
|
|
|
|
nsCOMPtr<mozIStoragePendingStatement> ps;
|
|
|
|
DebugOnly<nsresult> rv = conn->ExecuteSimpleSQLAsync(
|
|
|
|
shrinkPragma, nullptr, getter_AddRefs(ps));
|
|
|
|
MOZ_ASSERT(NS_SUCCEEDED(rv), "Should have purged sqlite caches");
|
|
|
|
} else {
|
|
|
|
conn->ExecuteSimpleSQL(shrinkPragma);
|
|
|
|
}
|
2015-01-28 02:00:23 +03:00
|
|
|
} else {
|
2022-09-21 18:02:14 +03:00
|
|
|
// We are on the wrong event target, the query should be executed on the
|
|
|
|
// opener event target, so we must dispatch to it.
|
2017-06-16 18:43:23 +03:00
|
|
|
// It's possible the connection is already closed or will be closed by the
|
2022-09-21 18:02:14 +03:00
|
|
|
// time our runnable runs. ExecuteSimpleSQL will safely return with a
|
|
|
|
// failure in that case. If the event target is shutting down or shut
|
|
|
|
// down, the dispatch will fail and that's okay.
|
2017-06-20 09:27:02 +03:00
|
|
|
nsCOMPtr<nsIRunnable> event = NewRunnableMethod<const nsCString>(
|
|
|
|
"Connection::ExecuteSimpleSQL", conn, &Connection::ExecuteSimpleSQL,
|
|
|
|
shrinkPragma);
|
2022-09-21 18:02:14 +03:00
|
|
|
Unused << conn->eventTargetOpenedOn->Dispatch(event, NS_DISPATCH_NORMAL);
|
2014-03-27 14:19:49 +04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-11-29 23:35:23 +03:00
|
|
|
UniquePtr<sqlite3_vfs> ConstructReadOnlyNoLockVFS();
|
|
|
|
|
2014-03-27 14:19:49 +04:00
|
|
|
static const char* sObserverTopics[] = {"memory-pressure",
|
|
|
|
"xpcom-shutdown-threads"};
|
|
|
|
|
2009-03-31 18:26:16 +04:00
|
|
|
nsresult Service::initialize() {
|
2013-02-08 21:08:22 +04:00
|
|
|
MOZ_ASSERT(NS_IsMainThread(), "Must be initialized on the main thread");
|
|
|
|
|
2017-09-29 14:25:06 +03:00
|
|
|
int rc = AutoSQLiteLifetime::getInitResult();
|
2020-10-29 13:13:46 +03:00
|
|
|
if (rc != SQLITE_OK) {
|
|
|
|
return convertResultCode(rc);
|
|
|
|
}
|
2009-03-31 18:26:16 +04:00
|
|
|
|
2023-03-07 17:27:07 +03:00
|
|
|
/**
|
|
|
|
* The virtual file system hierarchy
|
|
|
|
*
|
|
|
|
* obfsvfs
|
|
|
|
* |
|
|
|
|
* |
|
|
|
|
* |
|
|
|
|
* quotavfs
|
|
|
|
* / \
|
|
|
|
* / \
|
|
|
|
* / \
|
|
|
|
* / \
|
|
|
|
* / \
|
2023-05-10 14:51:48 +03:00
|
|
|
* base-vfs-excl base-vfs
|
2023-03-07 17:27:07 +03:00
|
|
|
* / \ / \
|
|
|
|
* / \ / \
|
|
|
|
* / \ / \
|
|
|
|
* unix-excl win32 unix win32
|
|
|
|
*/
|
|
|
|
|
2023-09-26 17:51:38 +03:00
|
|
|
rc = mBaseSqliteVFS.Init(basevfs::ConstructVFS(false));
|
2020-10-29 13:13:46 +03:00
|
|
|
if (rc != SQLITE_OK) {
|
|
|
|
return convertResultCode(rc);
|
Bug 1650201 - Fix mozStorage prefs read before profile and fallback to a non-exclusive VFS when it can't get an exclusive lock. r=asuth,geckoview-reviewers,agi
mozStorage used to read prefs on service init, because they could only be read
on the main-thread. When service init was moved earlier, it started trying
to read prefs too early, before the profile was set up, thus it ended up always
reading the default value.
This patch moves the only relevant pref to mirrored StaticPrefs that can be accessed
from different threads, and removes two preferences that apparently are not necessary
(they have been broken from a long time) for now.
In particular, providing a global synchronous setting is a footgun, each consumer should
decide about their synchronous needs, rather than abusing a dangerous "go fast" setting.
The page size is something we don't change from quite some time, and it's unlikely to be
used to run experiments in the wild before doing local measurements first, for which Try
builds are enough.
The remaining exclusiveLock pref is a bit controversial, because in general exclusive lock
is better for various reasons, and mostly it is necessary to use WAL on network shares.
Though developers may find it useful for debugging, and some third parties are doing
dangerous things (like copying over databases) to work around it, for which it's safer to
provide a less dangerous alternative.
Note exclusive lock only works on Unix-derived systems for now (no Windows implementation).
Finally, this introduces a fallback to exclusive lock, so that if a third party is using our
databases, so that we can't get an exclusive lock, we'll fallback to normal locking.
Differential Revision: https://phabricator.services.mozilla.com/D82717
2020-07-11 00:45:53 +03:00
|
|
|
}
|
2020-10-29 13:13:46 +03:00
|
|
|
|
2023-09-26 17:51:38 +03:00
|
|
|
rc = mBaseExclSqliteVFS.Init(basevfs::ConstructVFS(true));
|
2020-10-29 13:13:46 +03:00
|
|
|
if (rc != SQLITE_OK) {
|
|
|
|
return convertResultCode(rc);
|
|
|
|
}
|
|
|
|
|
2023-09-26 17:51:38 +03:00
|
|
|
rc = mQuotaSqliteVFS.Init(quotavfs::ConstructVFS(basevfs::GetVFSName(
|
|
|
|
StaticPrefs::storage_sqlite_exclusiveLock_enabled())));
|
2020-10-29 13:13:46 +03:00
|
|
|
if (rc != SQLITE_OK) {
|
|
|
|
return convertResultCode(rc);
|
2013-01-30 01:38:37 +04:00
|
|
|
}
|
|
|
|
|
2023-09-26 17:51:38 +03:00
|
|
|
rc =
|
|
|
|
mObfuscatingSqliteVFS.Init(obfsvfs::ConstructVFS(quotavfs::GetVFSName()));
|
2023-03-07 17:27:07 +03:00
|
|
|
if (rc != SQLITE_OK) {
|
|
|
|
return convertResultCode(rc);
|
|
|
|
}
|
|
|
|
|
2022-11-29 23:35:23 +03:00
|
|
|
rc = mReadOnlyNoLockSqliteVFS.Init(ConstructReadOnlyNoLockVFS());
|
|
|
|
if (rc != SQLITE_OK) {
|
|
|
|
return convertResultCode(rc);
|
|
|
|
}
|
|
|
|
|
2013-02-08 21:08:22 +04:00
|
|
|
nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
|
|
|
|
NS_ENSURE_TRUE(os, NS_ERROR_FAILURE);
|
2014-03-27 14:19:49 +04:00
|
|
|
|
2023-06-24 13:11:28 +03:00
|
|
|
for (auto& sObserverTopic : sObserverTopics) {
|
|
|
|
nsresult rv = os->AddObserver(this, sObserverTopic, false);
|
2014-03-27 14:19:49 +04:00
|
|
|
if (NS_WARN_IF(NS_FAILED(rv))) {
|
|
|
|
return rv;
|
|
|
|
}
|
|
|
|
}
|
2013-02-08 21:08:22 +04:00
|
|
|
|
2013-11-07 09:35:30 +04:00
|
|
|
mozilla::RegisterWeakMemoryReporter(this);
|
2013-09-20 02:52:30 +04:00
|
|
|
mozilla::RegisterStorageSQLiteDistinguishedAmount(
|
|
|
|
StorageSQLiteDistinguishedAmount);
|
2009-03-31 18:26:16 +04:00
|
|
|
|
|
|
|
return NS_OK;
|
2004-10-09 04:04:10 +04:00
|
|
|
}
|
|
|
|
|
2009-07-15 21:49:05 +04:00
|
|
|
int Service::localeCompareStrings(const nsAString& aStr1,
|
|
|
|
const nsAString& aStr2,
|
2021-08-10 19:01:18 +03:00
|
|
|
Collator::Sensitivity aSensitivity) {
|
|
|
|
// The mozilla::intl::Collator is not thread safe, since the Collator::Options
|
|
|
|
// can be changed.
|
2009-07-15 21:49:05 +04:00
|
|
|
MutexAutoLock mutex(mMutex);
|
|
|
|
|
2021-08-10 19:01:18 +03:00
|
|
|
Collator* collator = getCollator();
|
|
|
|
if (!collator) {
|
2009-07-15 21:49:05 +04:00
|
|
|
NS_ERROR("Storage service has no collation");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2021-08-10 19:01:18 +03:00
|
|
|
if (aSensitivity != mLastSensitivity) {
|
|
|
|
Collator::Options options{};
|
|
|
|
options.sensitivity = aSensitivity;
|
|
|
|
auto result = mCollator->SetOptions(options);
|
|
|
|
|
|
|
|
if (result.isErr()) {
|
|
|
|
NS_WARNING("Could not configure the mozilla::intl::Collation.");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
mLastSensitivity = aSensitivity;
|
2009-07-15 21:49:05 +04:00
|
|
|
}
|
|
|
|
|
2021-08-10 19:01:18 +03:00
|
|
|
return collator->CompareStrings(aStr1, aStr2);
|
2009-07-15 21:49:05 +04:00
|
|
|
}
|
|
|
|
|
2021-08-10 19:01:18 +03:00
|
|
|
Collator* Service::getCollator() {
|
2009-07-15 21:49:05 +04:00
|
|
|
mMutex.AssertCurrentThreadOwns();
|
|
|
|
|
2021-08-10 19:01:18 +03:00
|
|
|
if (mCollator) {
|
|
|
|
return mCollator.get();
|
|
|
|
}
|
2009-07-15 21:49:05 +04:00
|
|
|
|
2021-08-10 19:01:18 +03:00
|
|
|
auto result = mozilla::intl::LocaleService::TryCreateComponent<Collator>();
|
|
|
|
if (result.isErr()) {
|
|
|
|
NS_WARNING("Could not create mozilla::intl::Collation.");
|
2012-07-30 18:20:58 +04:00
|
|
|
return nullptr;
|
2009-07-15 21:49:05 +04:00
|
|
|
}
|
|
|
|
|
2021-08-10 19:01:18 +03:00
|
|
|
mCollator = result.unwrap();
|
|
|
|
|
|
|
|
// Sort in a case-insensitive way, where "base" letters are considered
|
|
|
|
// equal, e.g: a = á, a = A, a ≠ b.
|
|
|
|
Collator::Options options{};
|
|
|
|
options.sensitivity = Collator::Sensitivity::Base;
|
|
|
|
auto optResult = mCollator->SetOptions(options);
|
|
|
|
|
|
|
|
if (optResult.isErr()) {
|
|
|
|
NS_WARNING("Could not configure the mozilla::intl::Collation.");
|
|
|
|
mCollator = nullptr;
|
2012-07-30 18:20:58 +04:00
|
|
|
return nullptr;
|
2009-07-15 21:49:05 +04:00
|
|
|
}
|
|
|
|
|
2021-08-10 19:01:18 +03:00
|
|
|
return mCollator.get();
|
2009-07-15 21:49:05 +04:00
|
|
|
}
|
|
|
|
|
2009-01-22 00:52:16 +03:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
//// mozIStorageService
|
|
|
|
|
2004-10-09 04:04:10 +04:00
|
|
|
NS_IMETHODIMP
|
2020-11-11 10:26:41 +03:00
|
|
|
Service::OpenSpecialDatabase(const nsACString& aStorageKey,
|
2022-02-17 09:22:27 +03:00
|
|
|
const nsACString& aName, uint32_t aConnectionFlags,
|
2009-03-31 18:26:16 +04:00
|
|
|
mozIStorageConnection** _connection) {
|
2020-11-11 10:26:41 +03:00
|
|
|
if (!aStorageKey.Equals(kMozStorageMemoryStorageKey)) {
|
2009-03-31 18:26:16 +04:00
|
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
}
|
|
|
|
|
2022-02-17 09:22:27 +03:00
|
|
|
const bool interruptible =
|
|
|
|
aConnectionFlags & mozIStorageService::CONNECTION_INTERRUPTIBLE;
|
|
|
|
|
2020-11-13 01:01:32 +03:00
|
|
|
int flags = SQLITE_OPEN_READWRITE;
|
|
|
|
|
|
|
|
if (!aName.IsEmpty()) {
|
|
|
|
flags |= SQLITE_OPEN_URI;
|
|
|
|
}
|
|
|
|
|
2023-06-24 13:11:28 +03:00
|
|
|
RefPtr<Connection> msc =
|
|
|
|
new Connection(this, flags, Connection::SYNCHRONOUS,
|
|
|
|
kMozStorageMemoryStorageKey, interruptible);
|
2022-02-17 09:22:27 +03:00
|
|
|
const nsresult rv = msc->initialize(aStorageKey, aName);
|
2009-03-31 18:26:16 +04:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
2012-12-17 23:25:10 +04:00
|
|
|
msc.forget(_connection);
|
2009-03-31 18:26:16 +04:00
|
|
|
return NS_OK;
|
2004-10-09 04:04:10 +04:00
|
|
|
}
|
|
|
|
|
2013-06-27 17:00:59 +04:00
|
|
|
namespace {
|
|
|
|
|
2016-04-26 03:23:21 +03:00
|
|
|
class AsyncInitDatabase final : public Runnable {
|
2013-06-27 17:00:59 +04:00
|
|
|
public:
|
|
|
|
AsyncInitDatabase(Connection* aConnection, nsIFile* aStorageFile,
|
|
|
|
int32_t aGrowthIncrement,
|
|
|
|
mozIStorageCompletionCallback* aCallback)
|
2017-06-12 22:34:10 +03:00
|
|
|
: Runnable("storage::AsyncInitDatabase"),
|
|
|
|
mConnection(aConnection),
|
2013-06-27 17:00:59 +04:00
|
|
|
mStorageFile(aStorageFile),
|
|
|
|
mGrowthIncrement(aGrowthIncrement),
|
|
|
|
mCallback(aCallback) {
|
|
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
}
|
|
|
|
|
2016-08-08 05:18:10 +03:00
|
|
|
NS_IMETHOD Run() override {
|
2013-06-27 17:00:59 +04:00
|
|
|
MOZ_ASSERT(!NS_IsMainThread());
|
2017-06-16 18:43:23 +03:00
|
|
|
nsresult rv = mConnection->initializeOnAsyncThread(mStorageFile);
|
2013-06-27 17:00:59 +04:00
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return DispatchResult(rv, nullptr);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mGrowthIncrement >= 0) {
|
|
|
|
// Ignore errors. In the future, we might wish to log them.
|
2020-09-23 18:17:15 +03:00
|
|
|
(void)mConnection->SetGrowthIncrement(mGrowthIncrement, ""_ns);
|
2013-06-27 17:00:59 +04:00
|
|
|
}
|
|
|
|
|
|
|
|
return DispatchResult(
|
|
|
|
NS_OK, NS_ISUPPORTS_CAST(mozIStorageAsyncConnection*, mConnection));
|
|
|
|
}
|
|
|
|
|
|
|
|
private:
|
|
|
|
nsresult DispatchResult(nsresult aStatus, nsISupports* aValue) {
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<CallbackComplete> event =
|
2013-06-27 17:00:59 +04:00
|
|
|
new CallbackComplete(aStatus, aValue, mCallback.forget());
|
|
|
|
return NS_DispatchToMainThread(event);
|
|
|
|
}
|
|
|
|
|
|
|
|
~AsyncInitDatabase() {
|
2020-04-07 18:16:23 +03:00
|
|
|
NS_ReleaseOnMainThread("AsyncInitDatabase::mStorageFile",
|
|
|
|
mStorageFile.forget());
|
|
|
|
NS_ReleaseOnMainThread("AsyncInitDatabase::mConnection",
|
|
|
|
mConnection.forget());
|
2013-06-27 17:00:59 +04:00
|
|
|
|
|
|
|
// Generally, the callback will be released by CallbackComplete.
|
|
|
|
// However, if for some reason Run() is not executed, we still
|
|
|
|
// need to ensure that it is released here.
|
2020-04-07 18:16:23 +03:00
|
|
|
NS_ReleaseOnMainThread("AsyncInitDatabase::mCallback", mCallback.forget());
|
2013-06-27 17:00:59 +04:00
|
|
|
}
|
|
|
|
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<Connection> mConnection;
|
2013-06-27 17:00:59 +04:00
|
|
|
nsCOMPtr<nsIFile> mStorageFile;
|
|
|
|
int32_t mGrowthIncrement;
|
2015-10-18 08:24:48 +03:00
|
|
|
RefPtr<mozIStorageCompletionCallback> mCallback;
|
2013-06-27 17:00:59 +04:00
|
|
|
};
|
|
|
|
|
2015-07-13 18:25:42 +03:00
|
|
|
} // namespace
|
2013-06-27 17:00:59 +04:00
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2022-02-17 09:22:27 +03:00
|
|
|
Service::OpenAsyncDatabase(nsIVariant* aDatabaseStore, uint32_t aOpenFlags,
|
|
|
|
uint32_t /* aConnectionFlags */,
|
2013-06-27 17:00:59 +04:00
|
|
|
mozIStorageCompletionCallback* aCallback) {
|
|
|
|
if (!NS_IsMainThread()) {
|
|
|
|
return NS_ERROR_NOT_SAME_THREAD;
|
|
|
|
}
|
|
|
|
NS_ENSURE_ARG(aDatabaseStore);
|
|
|
|
NS_ENSURE_ARG(aCallback);
|
|
|
|
|
2022-02-17 09:22:27 +03:00
|
|
|
const bool shared = aOpenFlags & mozIStorageService::OPEN_SHARED;
|
|
|
|
const bool ignoreLockingMode =
|
|
|
|
aOpenFlags & mozIStorageService::OPEN_IGNORE_LOCKING_MODE;
|
|
|
|
// Specifying ignoreLockingMode will force use of the readOnly flag:
|
|
|
|
const bool readOnly =
|
|
|
|
ignoreLockingMode || (aOpenFlags & mozIStorageService::OPEN_READONLY);
|
2024-06-12 03:17:58 +03:00
|
|
|
const bool openNotExclusive =
|
|
|
|
aOpenFlags & mozIStorageService::OPEN_NOT_EXCLUSIVE;
|
2016-07-18 18:46:45 +03:00
|
|
|
int flags = readOnly ? SQLITE_OPEN_READONLY : SQLITE_OPEN_READWRITE;
|
2016-09-16 06:04:30 +03:00
|
|
|
|
2016-07-18 18:46:45 +03:00
|
|
|
nsCOMPtr<nsIFile> storageFile;
|
2013-06-27 17:00:59 +04:00
|
|
|
nsCOMPtr<nsISupports> dbStore;
|
2022-02-17 09:22:27 +03:00
|
|
|
nsresult rv = aDatabaseStore->GetAsISupports(getter_AddRefs(dbStore));
|
2013-06-27 17:00:59 +04:00
|
|
|
if (NS_SUCCEEDED(rv)) {
|
|
|
|
// Generally, aDatabaseStore holds the database nsIFile.
|
|
|
|
storageFile = do_QueryInterface(dbStore, &rv);
|
|
|
|
if (NS_FAILED(rv)) {
|
|
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
}
|
|
|
|
|
2018-10-05 23:23:40 +03:00
|
|
|
nsCOMPtr<nsIFile> cloned;
|
|
|
|
rv = storageFile->Clone(getter_AddRefs(cloned));
|
2013-06-27 17:00:59 +04:00
|
|
|
MOZ_ASSERT(NS_SUCCEEDED(rv));
|
2020-02-13 17:38:48 +03:00
|
|
|
storageFile = std::move(cloned);
|
2013-06-27 17:00:59 +04:00
|
|
|
|
2016-07-18 18:46:45 +03:00
|
|
|
if (!readOnly) {
|
|
|
|
// Ensure that SQLITE_OPEN_CREATE is passed in for compatibility reasons.
|
|
|
|
flags |= SQLITE_OPEN_CREATE;
|
2016-09-16 06:04:30 +03:00
|
|
|
}
|
2016-07-18 18:46:45 +03:00
|
|
|
|
|
|
|
// Apply the shared-cache option.
|
2013-06-27 17:00:59 +04:00
|
|
|
flags |= shared ? SQLITE_OPEN_SHAREDCACHE : SQLITE_OPEN_PRIVATECACHE;
|
|
|
|
} else {
|
|
|
|
// Sometimes, however, it's a special database name.
|
|
|
|
nsAutoCString keyString;
|
|
|
|
rv = aDatabaseStore->GetAsACString(keyString);
|
2020-11-11 10:26:41 +03:00
|
|
|
if (NS_FAILED(rv) || !keyString.Equals(kMozStorageMemoryStorageKey)) {
|
2013-06-27 17:00:59 +04:00
|
|
|
return NS_ERROR_INVALID_ARG;
|
|
|
|
}
|
|
|
|
|
2013-07-31 19:44:58 +04:00
|
|
|
// Just fall through with nullptr storageFile, this will cause the storage
|
2013-06-27 17:00:59 +04:00
|
|
|
// connection to use a memory DB.
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create connection on this thread, but initialize it on its helper thread.
|
2023-06-24 13:11:28 +03:00
|
|
|
nsAutoCString telemetryFilename;
|
|
|
|
if (!storageFile) {
|
2023-06-24 13:11:28 +03:00
|
|
|
telemetryFilename.Assign(kMozStorageMemoryStorageKey);
|
2023-06-24 13:11:28 +03:00
|
|
|
} else {
|
|
|
|
rv = storageFile->GetNativeLeafName(telemetryFilename);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
}
|
2024-06-12 03:17:58 +03:00
|
|
|
RefPtr<Connection> msc = new Connection(
|
|
|
|
this, flags, Connection::ASYNCHRONOUS, telemetryFilename,
|
|
|
|
/* interruptible */ true, ignoreLockingMode, openNotExclusive);
|
2013-06-27 17:00:59 +04:00
|
|
|
nsCOMPtr<nsIEventTarget> target = msc->getAsyncExecutionTarget();
|
|
|
|
MOZ_ASSERT(target,
|
|
|
|
"Cannot initialize a connection that has been closed already");
|
|
|
|
|
2022-02-17 09:22:27 +03:00
|
|
|
RefPtr<AsyncInitDatabase> asyncInit = new AsyncInitDatabase(
|
|
|
|
msc, storageFile, /* growthIncrement */ -1, aCallback);
|
2013-06-27 17:00:59 +04:00
|
|
|
return target->Dispatch(asyncInit, nsIEventTarget::DISPATCH_NORMAL);
|
|
|
|
}
|
|
|
|
|
2004-10-09 04:04:10 +04:00
|
|
|
NS_IMETHODIMP
|
2022-02-17 09:22:27 +03:00
|
|
|
Service::OpenDatabase(nsIFile* aDatabaseFile, uint32_t aConnectionFlags,
|
2009-03-31 18:26:16 +04:00
|
|
|
mozIStorageConnection** _connection) {
|
2010-08-03 01:29:59 +04:00
|
|
|
NS_ENSURE_ARG(aDatabaseFile);
|
|
|
|
|
2022-02-17 09:22:27 +03:00
|
|
|
const bool interruptible =
|
|
|
|
aConnectionFlags & mozIStorageService::CONNECTION_INTERRUPTIBLE;
|
|
|
|
|
2010-08-27 23:42:58 +04:00
|
|
|
// Always ensure that SQLITE_OPEN_CREATE is passed in for compatibility
|
|
|
|
// reasons.
|
2022-02-17 09:22:27 +03:00
|
|
|
const int flags =
|
2010-08-27 23:42:58 +04:00
|
|
|
SQLITE_OPEN_READWRITE | SQLITE_OPEN_SHAREDCACHE | SQLITE_OPEN_CREATE;
|
2023-06-24 13:11:28 +03:00
|
|
|
nsAutoCString telemetryFilename;
|
|
|
|
nsresult rv = aDatabaseFile->GetNativeLeafName(telemetryFilename);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
RefPtr<Connection> msc = new Connection(this, flags, Connection::SYNCHRONOUS,
|
|
|
|
telemetryFilename, interruptible);
|
|
|
|
rv = msc->initialize(aDatabaseFile);
|
2010-08-27 23:42:55 +04:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2008-02-09 22:05:49 +03:00
|
|
|
|
2012-12-17 23:25:10 +04:00
|
|
|
msc.forget(_connection);
|
2009-03-31 18:26:16 +04:00
|
|
|
return NS_OK;
|
2004-10-09 04:04:10 +04:00
|
|
|
}
|
2008-01-30 02:34:19 +03:00
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2022-02-17 09:22:27 +03:00
|
|
|
Service::OpenUnsharedDatabase(nsIFile* aDatabaseFile, uint32_t aConnectionFlags,
|
2009-03-31 18:26:16 +04:00
|
|
|
mozIStorageConnection** _connection) {
|
2011-07-02 02:53:41 +04:00
|
|
|
NS_ENSURE_ARG(aDatabaseFile);
|
|
|
|
|
2022-02-17 09:22:27 +03:00
|
|
|
const bool interruptible =
|
|
|
|
aConnectionFlags & mozIStorageService::CONNECTION_INTERRUPTIBLE;
|
|
|
|
|
2010-08-27 23:42:58 +04:00
|
|
|
// Always ensure that SQLITE_OPEN_CREATE is passed in for compatibility
|
|
|
|
// reasons.
|
2022-02-17 09:22:27 +03:00
|
|
|
const int flags =
|
2010-08-27 23:42:58 +04:00
|
|
|
SQLITE_OPEN_READWRITE | SQLITE_OPEN_PRIVATECACHE | SQLITE_OPEN_CREATE;
|
2023-06-24 13:11:28 +03:00
|
|
|
nsAutoCString telemetryFilename;
|
|
|
|
nsresult rv = aDatabaseFile->GetNativeLeafName(telemetryFilename);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
RefPtr<Connection> msc = new Connection(this, flags, Connection::SYNCHRONOUS,
|
|
|
|
telemetryFilename, interruptible);
|
|
|
|
rv = msc->initialize(aDatabaseFile);
|
2009-03-31 18:26:16 +04:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
2008-03-25 01:14:38 +03:00
|
|
|
|
2012-12-17 23:25:10 +04:00
|
|
|
msc.forget(_connection);
|
|
|
|
return NS_OK;
|
|
|
|
}
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
|
|
|
Service::OpenDatabaseWithFileURL(nsIFileURL* aFileURL,
|
2020-08-11 23:55:33 +03:00
|
|
|
const nsACString& aTelemetryFilename,
|
2022-02-17 09:22:27 +03:00
|
|
|
uint32_t aConnectionFlags,
|
2012-12-17 23:25:10 +04:00
|
|
|
mozIStorageConnection** _connection) {
|
|
|
|
NS_ENSURE_ARG(aFileURL);
|
|
|
|
|
2022-02-17 09:22:27 +03:00
|
|
|
const bool interruptible =
|
|
|
|
aConnectionFlags & mozIStorageService::CONNECTION_INTERRUPTIBLE;
|
|
|
|
|
2012-12-17 23:25:10 +04:00
|
|
|
// Always ensure that SQLITE_OPEN_CREATE is passed in for compatibility
|
|
|
|
// reasons.
|
2022-02-17 09:22:27 +03:00
|
|
|
const int flags = SQLITE_OPEN_READWRITE | SQLITE_OPEN_SHAREDCACHE |
|
|
|
|
SQLITE_OPEN_CREATE | SQLITE_OPEN_URI;
|
2023-06-24 13:11:28 +03:00
|
|
|
nsresult rv;
|
|
|
|
nsAutoCString telemetryFilename;
|
|
|
|
if (!aTelemetryFilename.IsEmpty()) {
|
|
|
|
telemetryFilename = aTelemetryFilename;
|
|
|
|
} else {
|
|
|
|
nsCOMPtr<nsIFile> databaseFile;
|
|
|
|
rv = aFileURL->GetFile(getter_AddRefs(databaseFile));
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
rv = databaseFile->GetNativeLeafName(telemetryFilename);
|
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
}
|
|
|
|
RefPtr<Connection> msc = new Connection(this, flags, Connection::SYNCHRONOUS,
|
|
|
|
telemetryFilename, interruptible);
|
|
|
|
rv = msc->initialize(aFileURL);
|
2012-12-17 23:25:10 +04:00
|
|
|
NS_ENSURE_SUCCESS(rv, rv);
|
|
|
|
|
|
|
|
msc.forget(_connection);
|
2009-03-31 18:26:16 +04:00
|
|
|
return NS_OK;
|
|
|
|
}
|
2008-03-25 01:14:38 +03:00
|
|
|
|
2009-01-22 00:52:16 +03:00
|
|
|
////////////////////////////////////////////////////////////////////////////////
|
|
|
|
//// nsIObserver
|
|
|
|
|
|
|
|
NS_IMETHODIMP
|
2014-01-04 19:02:17 +04:00
|
|
|
Service::Observe(nsISupports*, const char* aTopic, const char16_t*) {
|
2014-03-27 14:19:49 +04:00
|
|
|
if (strcmp(aTopic, "memory-pressure") == 0) {
|
|
|
|
minimizeMemory();
|
|
|
|
} else if (strcmp(aTopic, "xpcom-shutdown-threads") == 0) {
|
2017-08-11 06:26:25 +03:00
|
|
|
// The Service is kept alive by our strong observer references and
|
|
|
|
// references held by Connection instances. Since we're about to remove the
|
|
|
|
// former and then wait for the latter ones to go away, it behooves us to
|
|
|
|
// hold a strong reference to ourselves so our calls to getConnections() do
|
|
|
|
// not happen on a deleted object.
|
|
|
|
RefPtr<Service> kungFuDeathGrip = this;
|
|
|
|
|
2012-05-08 22:58:56 +04:00
|
|
|
nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
|
2014-03-27 14:19:49 +04:00
|
|
|
|
2023-06-24 13:11:28 +03:00
|
|
|
for (auto& sObserverTopic : sObserverTopics) {
|
|
|
|
(void)os->RemoveObserver(this, sObserverTopic);
|
2014-03-27 14:19:49 +04:00
|
|
|
}
|
|
|
|
|
2021-10-07 11:06:14 +03:00
|
|
|
SpinEventLoopUntil("storage::Service::Observe(xpcom-shutdown-threads)"_ns,
|
|
|
|
[&]() -> bool {
|
|
|
|
// We must wait until all the closing connections are
|
|
|
|
// closed.
|
|
|
|
nsTArray<RefPtr<Connection>> connections;
|
|
|
|
getConnections(connections);
|
|
|
|
for (auto& conn : connections) {
|
|
|
|
if (conn->isClosing()) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
});
|
2012-05-24 21:08:22 +04:00
|
|
|
|
2017-10-18 14:04:52 +03:00
|
|
|
#ifdef DEBUG
|
Bug 1606880 - Implement fast shutdown prefs r=froydnj
I originally had this as a few patches, but the work to fix test
failures and get the whole thing into a complete working state
quickly tangled them up. Apologies for that. To summarize what's
going on here, however:
- We introduce two prefs: shutdown.fastShutdownStage and
shutdown.lateWriteChecksStage. The latter pref is set to 1, which
will leave the existing late write checking behavior unchanged.
However, we introduce this pref to make it simpler in the future
to bump the late write checks window earlier in the shutdown cycle.
- We introduce an AppShutdown class, which will house static methods
and a small amount of state for unifying some shutdown logic. Most
importantly, it will now manage the state for app initiated restarts,
as well as the logic for performing a safe fast shutdown.
- We refactored the existing restart code to call into the new
AppShutdown file, so that if we are configured to actually perform
a fast shutdown, we will be able to run the necessary restart logic
immediately before doing so. Previously, the restart logic occurred
later in the shutdown cycle than our late write checking, meaning
if we were to simply exit the process at that point in time, we
would never run the restart coe.
- Lastly, we updated two locations which called TerminateProcess and/or
_exit(0) to call into the AppShutdown method (DoFastShutdown).
Differential Revision: https://phabricator.services.mozilla.com/D59196
--HG--
extra : moz-landing-system : lando
2020-01-29 15:29:43 +03:00
|
|
|
nsTArray<RefPtr<Connection>> connections;
|
|
|
|
getConnections(connections);
|
|
|
|
for (uint32_t i = 0, n = connections.Length(); i < n; i++) {
|
|
|
|
if (!connections[i]->isClosed()) {
|
|
|
|
// getFilename is only the leaf name for the database file,
|
|
|
|
// so it shouldn't contain privacy-sensitive information.
|
Bug 1831092 - Use the new pull-based API for all crash annotations and remove the global annotations table r=jgilbert,necko-reviewers,media-playback-reviewers,profiler-reviewers,win-reviewers,padenot,handyman,afranchuk,valentin,alwu,sotaro
This changes comes with several different refactorings all rolled into one,
unfotunately I couldn't find a way to pull them apart:
- First of all annotations now can either recorded (that is, we copy the value
and have the crash reporting code own the copy) or registered. Several
annotations are changed to use this functionality so that we don't need to
update them as their value change.
- The code in the exception handler is modified to read the annotations from
the mozannotation_client crate. This has the unfortunate side-effect that
we need three different bits of code to serialize them: one for annotations
read from a child process, one for reading annotations from the main process
outside of the exception handler and one for reading annotations from the
main process within the exception handler. As we move to fully
out-of-process crash reporting the last two methods will go away.
- The mozannotation_client crate now doesn't record annotation types anymore.
I realized as I was working on this that storing types at runtime has two
issues: the first one is that buggy code might change the type of an
annotation (that is record it under two different types at two different
moments), the second issue is that types might become corrupt during a
crash, so better enforce them at annotation-writing time. The end result is
that the mozannotation_* crates now only store byte buffers, track the
format the data is stored in (null-terminated string, fixed size buffer,
etc...) but not the type of data each annotation is supposed to contain.
- Which brings us to the next change: concrete types for annotations are now
enforced when they're written out. If an annotation doesn't match the
expected type it's skipped. Storing an annotation with the wrong type will
also trigger an assertion in debug builds.
Differential Revision: https://phabricator.services.mozilla.com/D195248
2024-03-04 13:24:43 +03:00
|
|
|
CrashReporter::RecordAnnotationNSCString(
|
Bug 1606880 - Implement fast shutdown prefs r=froydnj
I originally had this as a few patches, but the work to fix test
failures and get the whole thing into a complete working state
quickly tangled them up. Apologies for that. To summarize what's
going on here, however:
- We introduce two prefs: shutdown.fastShutdownStage and
shutdown.lateWriteChecksStage. The latter pref is set to 1, which
will leave the existing late write checking behavior unchanged.
However, we introduce this pref to make it simpler in the future
to bump the late write checks window earlier in the shutdown cycle.
- We introduce an AppShutdown class, which will house static methods
and a small amount of state for unifying some shutdown logic. Most
importantly, it will now manage the state for app initiated restarts,
as well as the logic for performing a safe fast shutdown.
- We refactored the existing restart code to call into the new
AppShutdown file, so that if we are configured to actually perform
a fast shutdown, we will be able to run the necessary restart logic
immediately before doing so. Previously, the restart logic occurred
later in the shutdown cycle than our late write checking, meaning
if we were to simply exit the process at that point in time, we
would never run the restart coe.
- Lastly, we updated two locations which called TerminateProcess and/or
_exit(0) to call into the AppShutdown method (DoFastShutdown).
Differential Revision: https://phabricator.services.mozilla.com/D59196
--HG--
extra : moz-landing-system : lando
2020-01-29 15:29:43 +03:00
|
|
|
CrashReporter::Annotation::StorageConnectionNotClosed,
|
|
|
|
connections[i]->getFilename());
|
|
|
|
printf_stderr("Storage connection not closed: %s",
|
|
|
|
connections[i]->getFilename().get());
|
|
|
|
MOZ_CRASH();
|
2013-02-11 21:05:59 +04:00
|
|
|
}
|
2012-05-24 21:08:22 +04:00
|
|
|
}
|
Bug 1606880 - Implement fast shutdown prefs r=froydnj
I originally had this as a few patches, but the work to fix test
failures and get the whole thing into a complete working state
quickly tangled them up. Apologies for that. To summarize what's
going on here, however:
- We introduce two prefs: shutdown.fastShutdownStage and
shutdown.lateWriteChecksStage. The latter pref is set to 1, which
will leave the existing late write checking behavior unchanged.
However, we introduce this pref to make it simpler in the future
to bump the late write checks window earlier in the shutdown cycle.
- We introduce an AppShutdown class, which will house static methods
and a small amount of state for unifying some shutdown logic. Most
importantly, it will now manage the state for app initiated restarts,
as well as the logic for performing a safe fast shutdown.
- We refactored the existing restart code to call into the new
AppShutdown file, so that if we are configured to actually perform
a fast shutdown, we will be able to run the necessary restart logic
immediately before doing so. Previously, the restart logic occurred
later in the shutdown cycle than our late write checking, meaning
if we were to simply exit the process at that point in time, we
would never run the restart coe.
- Lastly, we updated two locations which called TerminateProcess and/or
_exit(0) to call into the AppShutdown method (DoFastShutdown).
Differential Revision: https://phabricator.services.mozilla.com/D59196
--HG--
extra : moz-landing-system : lando
2020-01-29 15:29:43 +03:00
|
|
|
#endif
|
2012-05-08 22:58:56 +04:00
|
|
|
}
|
|
|
|
|
2009-03-31 18:26:16 +04:00
|
|
|
return NS_OK;
|
2009-01-22 00:52:16 +03:00
|
|
|
}
|
2009-03-31 18:26:16 +04:00
|
|
|
|
2023-06-24 13:11:28 +03:00
|
|
|
} // namespace mozilla::storage
|