Bug Summary

File:var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp
Warning:line 1550, column 5
Value stored to 'srv' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name mozStorageConnection.cpp -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/storage -fcoverage-compilation-dir=/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/storage -resource-dir /usr/lib/llvm-20/lib/clang/20 -include /var/lib/jenkins/workspace/firefox-scan-build/config/gcc_hidden.h -include /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/stl_wrappers -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D _GLIBCXX_ASSERTIONS -D DEBUG=1 -D MOZ_SQLITE_PERSIST_AUXILIARY_FILES=1 -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D MOZ_SUPPORT_LEAKCHECKING -D STATIC_EXPORTABLE_JS_API -I /var/lib/jenkins/workspace/firefox-scan-build/storage -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/storage -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/ipc/ipdl/_ipdlheaders -I /var/lib/jenkins/workspace/firefox-scan-build/ipc/chromium/src -I /var/lib/jenkins/workspace/firefox-scan-build/dom/base -I /var/lib/jenkins/workspace/firefox-scan-build/third_party/sqlite3/ext -I /var/lib/jenkins/workspace/firefox-scan-build/third_party/sqlite3/src -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/x86_64-linux-gnu/c++/14 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../include/c++/14/backward -internal-isystem /usr/lib/llvm-20/lib/clang/20/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-error=tautological-type-limit-compare -Wno-invalid-offsetof -Wno-range-loop-analysis -Wno-deprecated-anon-enum-enum-conversion -Wno-deprecated-enum-enum-conversion -Wno-deprecated-this-capture -Wno-inline-new-delete -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-vla-cxx-extension -Wno-unknown-warning-option -fdeprecated-macro -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fno-rtti -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -fno-sized-deallocation -fno-aligned-allocation -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2025-01-20-090804-167946-1 -x c++ /var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp
1/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2 * vim: sw=2 ts=2 et lcs=trail\:.,tab\:>~ :
3 * This Source Code Form is subject to the terms of the Mozilla Public
4 * License, v. 2.0. If a copy of the MPL was not distributed with this
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6
7#include "BaseVFS.h"
8#include "ErrorList.h"
9#include "nsError.h"
10#include "nsThreadUtils.h"
11#include "nsIFile.h"
12#include "nsIFileURL.h"
13#include "nsIXPConnect.h"
14#include "mozilla/AppShutdown.h"
15#include "mozilla/CheckedInt.h"
16#include "mozilla/Telemetry.h"
17#include "mozilla/Mutex.h"
18#include "mozilla/CondVar.h"
19#include "mozilla/Attributes.h"
20#include "mozilla/ErrorNames.h"
21#include "mozilla/Unused.h"
22#include "mozilla/dom/quota/QuotaObject.h"
23#include "mozilla/ScopeExit.h"
24#include "mozilla/SpinEventLoopUntil.h"
25#include "mozilla/StaticPrefs_storage.h"
26
27#include "mozIStorageCompletionCallback.h"
28#include "mozIStorageFunction.h"
29
30#include "mozStorageAsyncStatementExecution.h"
31#include "mozStorageSQLFunctions.h"
32#include "mozStorageConnection.h"
33#include "mozStorageService.h"
34#include "mozStorageStatement.h"
35#include "mozStorageAsyncStatement.h"
36#include "mozStorageArgValueArray.h"
37#include "mozStoragePrivateHelpers.h"
38#include "mozStorageStatementData.h"
39#include "ObfuscatingVFS.h"
40#include "QuotaVFS.h"
41#include "StorageBaseStatementInternal.h"
42#include "SQLCollations.h"
43#include "FileSystemModule.h"
44#include "mozStorageHelper.h"
45#include "sqlite3_static_ext.h"
46
47#include "mozilla/Assertions.h"
48#include "mozilla/Logging.h"
49#include "mozilla/Printf.h"
50#include "mozilla/ProfilerLabels.h"
51#include "mozilla/RefPtr.h"
52#include "nsComponentManagerUtils.h"
53#include "nsProxyRelease.h"
54#include "nsStringFwd.h"
55#include "nsURLHelper.h"
56
57#define MIN_AVAILABLE_BYTES_PER_CHUNKED_GROWTH524288000 524288000 // 500 MiB
58
59// Maximum size of the pages cache per connection.
60#define MAX_CACHE_SIZE_KIBIBYTES2048 2048 // 2 MiB
61
62mozilla::LazyLogModule gStorageLog("mozStorage");
63
64// Checks that the protected code is running on the main-thread only if the
65// connection was also opened on it.
66#ifdef DEBUG1
67# define CHECK_MAINTHREAD_ABUSE()do { do { if (!(eventTargetOpenedOn == GetMainThreadSerialEventTarget
() || !NS_IsMainThread())) { NS_DebugBreak(NS_DEBUG_WARNING, "Using Storage synchronous API on main-thread, but "
"the connection was opened on another thread.", "eventTargetOpenedOn == GetMainThreadSerialEventTarget() || !NS_IsMainThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 67); } } while (false); } while (0)
\
68 do { \
69 NS_WARNING_ASSERTION( \do { if (!(eventTargetOpenedOn == GetMainThreadSerialEventTarget
() || !NS_IsMainThread())) { NS_DebugBreak(NS_DEBUG_WARNING, "Using Storage synchronous API on main-thread, but "
"the connection was opened on another thread.", "eventTargetOpenedOn == GetMainThreadSerialEventTarget() || !NS_IsMainThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 73); } } while (false)
70 eventTargetOpenedOn == GetMainThreadSerialEventTarget() || \do { if (!(eventTargetOpenedOn == GetMainThreadSerialEventTarget
() || !NS_IsMainThread())) { NS_DebugBreak(NS_DEBUG_WARNING, "Using Storage synchronous API on main-thread, but "
"the connection was opened on another thread.", "eventTargetOpenedOn == GetMainThreadSerialEventTarget() || !NS_IsMainThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 73); } } while (false)
71 !NS_IsMainThread(), \do { if (!(eventTargetOpenedOn == GetMainThreadSerialEventTarget
() || !NS_IsMainThread())) { NS_DebugBreak(NS_DEBUG_WARNING, "Using Storage synchronous API on main-thread, but "
"the connection was opened on another thread.", "eventTargetOpenedOn == GetMainThreadSerialEventTarget() || !NS_IsMainThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 73); } } while (false)
72 "Using Storage synchronous API on main-thread, but " \do { if (!(eventTargetOpenedOn == GetMainThreadSerialEventTarget
() || !NS_IsMainThread())) { NS_DebugBreak(NS_DEBUG_WARNING, "Using Storage synchronous API on main-thread, but "
"the connection was opened on another thread.", "eventTargetOpenedOn == GetMainThreadSerialEventTarget() || !NS_IsMainThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 73); } } while (false)
73 "the connection was opened on another thread.")do { if (!(eventTargetOpenedOn == GetMainThreadSerialEventTarget
() || !NS_IsMainThread())) { NS_DebugBreak(NS_DEBUG_WARNING, "Using Storage synchronous API on main-thread, but "
"the connection was opened on another thread.", "eventTargetOpenedOn == GetMainThreadSerialEventTarget() || !NS_IsMainThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 73); } } while (false)
; \
74 } while (0)
75#else
76# define CHECK_MAINTHREAD_ABUSE()do { do { if (!(eventTargetOpenedOn == GetMainThreadSerialEventTarget
() || !NS_IsMainThread())) { NS_DebugBreak(NS_DEBUG_WARNING, "Using Storage synchronous API on main-thread, but "
"the connection was opened on another thread.", "eventTargetOpenedOn == GetMainThreadSerialEventTarget() || !NS_IsMainThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 76); } } while (false); } while (0)
\
77 do { /* Nothing */ \
78 } while (0)
79#endif
80
81namespace mozilla::storage {
82
83using mozilla::dom::quota::QuotaObject;
84using mozilla::Telemetry::AccumulateCategoricalKeyed;
85using mozilla::Telemetry::LABELS_SQLITE_STORE_OPEN;
86using mozilla::Telemetry::LABELS_SQLITE_STORE_QUERY;
87
88namespace {
89
90int nsresultToSQLiteResult(nsresult aXPCOMResultCode) {
91 if (NS_SUCCEEDED(aXPCOMResultCode)((bool)(__builtin_expect(!!(!NS_FAILED_impl(aXPCOMResultCode)
), 1)))
) {
92 return SQLITE_OK0;
93 }
94
95 switch (aXPCOMResultCode) {
96 case NS_ERROR_FILE_CORRUPTED:
97 return SQLITE_CORRUPT11;
98 case NS_ERROR_FILE_ACCESS_DENIED:
99 return SQLITE_CANTOPEN14;
100 case NS_ERROR_STORAGE_BUSY:
101 return SQLITE_BUSY5;
102 case NS_ERROR_FILE_IS_LOCKED:
103 return SQLITE_LOCKED6;
104 case NS_ERROR_FILE_READ_ONLY:
105 return SQLITE_READONLY8;
106 case NS_ERROR_STORAGE_IOERR:
107 return SQLITE_IOERR10;
108 case NS_ERROR_FILE_NO_DEVICE_SPACE:
109 return SQLITE_FULL13;
110 case NS_ERROR_OUT_OF_MEMORY:
111 return SQLITE_NOMEM7;
112 case NS_ERROR_UNEXPECTED:
113 return SQLITE_MISUSE21;
114 case NS_ERROR_ABORT:
115 return SQLITE_ABORT4;
116 case NS_ERROR_STORAGE_CONSTRAINT:
117 return SQLITE_CONSTRAINT19;
118 default:
119 return SQLITE_ERROR1;
120 }
121
122 MOZ_MAKE_COMPILER_ASSUME_IS_UNREACHABLE("Must return in switch above!")do { do { static_assert( mozilla::detail::AssertionConditionType
<decltype(false)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("false" " (" "MOZ_ASSERT_UNREACHABLE: "
"Must return in switch above!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 122); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"MOZ_ASSERT_UNREACHABLE: " "Must return in switch above!" ")"
); do { *((volatile int*)__null) = 122; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); __builtin_unreachable
(); } while (false)
;
123}
124
125////////////////////////////////////////////////////////////////////////////////
126//// Variant Specialization Functions (variantToSQLiteT)
127
128int sqlite3_T_int(sqlite3_context* aCtx, int aValue) {
129 ::sqlite3_result_int(aCtx, aValue);
130 return SQLITE_OK0;
131}
132
133int sqlite3_T_int64(sqlite3_context* aCtx, sqlite3_int64 aValue) {
134 ::sqlite3_result_int64(aCtx, aValue);
135 return SQLITE_OK0;
136}
137
138int sqlite3_T_double(sqlite3_context* aCtx, double aValue) {
139 ::sqlite3_result_double(aCtx, aValue);
140 return SQLITE_OK0;
141}
142
143int sqlite3_T_text(sqlite3_context* aCtx, const nsCString& aValue) {
144 CheckedInt<int32_t> length(aValue.Length());
145 if (!length.isValid()) {
146 return SQLITE_MISUSE21;
147 }
148 ::sqlite3_result_text(aCtx, aValue.get(), length.value(), SQLITE_TRANSIENT((sqlite3_destructor_type)-1));
149 return SQLITE_OK0;
150}
151
152int sqlite3_T_text16(sqlite3_context* aCtx, const nsString& aValue) {
153 CheckedInt<int32_t> n_bytes =
154 CheckedInt<int32_t>(aValue.Length()) * sizeof(char16_t);
155 if (!n_bytes.isValid()) {
156 return SQLITE_MISUSE21;
157 }
158 ::sqlite3_result_text16(aCtx, aValue.get(), n_bytes.value(),
159 SQLITE_TRANSIENT((sqlite3_destructor_type)-1));
160 return SQLITE_OK0;
161}
162
163int sqlite3_T_null(sqlite3_context* aCtx) {
164 ::sqlite3_result_null(aCtx);
165 return SQLITE_OK0;
166}
167
168int sqlite3_T_blob(sqlite3_context* aCtx, const void* aData, int aSize) {
169 ::sqlite3_result_blob(aCtx, aData, aSize, free);
170 return SQLITE_OK0;
171}
172
173int sqlite3_T_array(sqlite3_context* aCtx, const void* aData, int aSize,
174 int aType) {
175 // Not supported for now.
176 return SQLITE_MISUSE21;
177}
178
179#include "variantToSQLiteT_impl.h"
180
181////////////////////////////////////////////////////////////////////////////////
182//// Modules
183
184struct Module {
185 const char* name;
186 int (*registerFunc)(sqlite3*, const char*);
187};
188
189Module gModules[] = {{"filesystem", RegisterFileSystemModule}};
190
191////////////////////////////////////////////////////////////////////////////////
192//// Local Functions
193
194int tracefunc(unsigned aReason, void* aClosure, void* aP, void* aX) {
195 switch (aReason) {
196 case SQLITE_TRACE_STMT0x01: {
197 // aP is a pointer to the prepared statement.
198 sqlite3_stmt* stmt = static_cast<sqlite3_stmt*>(aP);
199 // aX is a pointer to a string containing the unexpanded SQL or a comment,
200 // starting with "--"" in case of a trigger.
201 char* expanded = static_cast<char*>(aX);
202 // Simulate what sqlite_trace was doing.
203 if (!::strncmp(expanded, "--", 2)) {
204 MOZ_LOG(gStorageLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gStorageLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "TRACE_STMT on %p: '%s'", aClosure, expanded
); } } while (0)
205 ("TRACE_STMT on %p: '%s'", aClosure, expanded))do { const ::mozilla::LogModule* moz_real_module = gStorageLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "TRACE_STMT on %p: '%s'", aClosure, expanded
); } } while (0)
;
206 } else {
207 char* sql = ::sqlite3_expanded_sql(stmt);
208 MOZ_LOG(gStorageLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gStorageLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "TRACE_STMT on %p: '%s'", aClosure, sql); }
} while (0)
209 ("TRACE_STMT on %p: '%s'", aClosure, sql))do { const ::mozilla::LogModule* moz_real_module = gStorageLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "TRACE_STMT on %p: '%s'", aClosure, sql); }
} while (0)
;
210 ::sqlite3_free(sql);
211 }
212 break;
213 }
214 case SQLITE_TRACE_PROFILE0x02: {
215 // aX is pointer to a 64bit integer containing nanoseconds it took to
216 // execute the last command.
217 sqlite_int64 time = *(static_cast<sqlite_int64*>(aX)) / 1000000;
218 if (time > 0) {
219 MOZ_LOG(gStorageLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gStorageLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "TRACE_TIME on %p: %lldms", aClosure, time
); } } while (0)
220 ("TRACE_TIME on %p: %lldms", aClosure, time))do { const ::mozilla::LogModule* moz_real_module = gStorageLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "TRACE_TIME on %p: %lldms", aClosure, time
); } } while (0)
;
221 }
222 break;
223 }
224 }
225 return 0;
226}
227
228void basicFunctionHelper(sqlite3_context* aCtx, int aArgc,
229 sqlite3_value** aArgv) {
230 void* userData = ::sqlite3_user_data(aCtx);
231
232 mozIStorageFunction* func = static_cast<mozIStorageFunction*>(userData);
233
234 RefPtr<ArgValueArray> arguments(new ArgValueArray(aArgc, aArgv));
235 if (!arguments) return;
236
237 nsCOMPtr<nsIVariant> result;
238 nsresult rv = func->OnFunctionCall(arguments, getter_AddRefs(result));
239 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
240 nsAutoCString errorMessage;
241 GetErrorName(rv, errorMessage);
242 errorMessage.InsertLiteral("User function returned ", 0);
243 errorMessage.Append('!');
244
245 NS_WARNING(errorMessage.get())NS_DebugBreak(NS_DEBUG_WARNING, errorMessage.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 245)
;
246
247 ::sqlite3_result_error(aCtx, errorMessage.get(), -1);
248 ::sqlite3_result_error_code(aCtx, nsresultToSQLiteResult(rv));
249 return;
250 }
251 int retcode = variantToSQLiteT(aCtx, result);
252 if (retcode != SQLITE_OK0) {
253 NS_WARNING("User function returned invalid data type!")NS_DebugBreak(NS_DEBUG_WARNING, "User function returned invalid data type!"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 253)
;
254 ::sqlite3_result_error(aCtx, "User function returned invalid data type",
255 -1);
256 }
257}
258
259RefPtr<QuotaObject> GetQuotaObject(sqlite3_file* aFile, bool obfuscatingVFS) {
260 return obfuscatingVFS
261 ? mozilla::storage::obfsvfs::GetQuotaObjectForFile(aFile)
262 : mozilla::storage::quotavfs::GetQuotaObjectForFile(aFile);
263}
264
265/**
266 * This code is heavily based on the sample at:
267 * http://www.sqlite.org/unlock_notify.html
268 */
269class UnlockNotification {
270 public:
271 UnlockNotification()
272 : mMutex("UnlockNotification mMutex"),
273 mCondVar(mMutex, "UnlockNotification condVar"),
274 mSignaled(false) {}
275
276 void Wait() {
277 MutexAutoLock lock(mMutex);
278 while (!mSignaled) {
279 (void)mCondVar.Wait();
280 }
281 }
282
283 void Signal() {
284 MutexAutoLock lock(mMutex);
285 mSignaled = true;
286 (void)mCondVar.Notify();
287 }
288
289 private:
290 Mutex mMutex MOZ_UNANNOTATED;
291 CondVar mCondVar;
292 bool mSignaled;
293};
294
295void UnlockNotifyCallback(void** aArgs, int aArgsSize) {
296 for (int i = 0; i < aArgsSize; i++) {
297 UnlockNotification* notification =
298 static_cast<UnlockNotification*>(aArgs[i]);
299 notification->Signal();
300 }
301}
302
303int WaitForUnlockNotify(sqlite3* aDatabase) {
304 UnlockNotification notification;
305 int srv =
306 ::sqlite3_unlock_notify(aDatabase, UnlockNotifyCallback, &notification);
307 MOZ_ASSERT(srv == SQLITE_LOCKED || srv == SQLITE_OK)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(srv == 6 || srv == 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(srv == 6 || srv == 0))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("srv == 6 || srv == 0"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 307); AnnotateMozCrashReason("MOZ_ASSERT" "(" "srv == 6 || srv == 0"
")"); do { *((volatile int*)__null) = 307; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
308 if (srv == SQLITE_OK0) {
309 notification.Wait();
310 }
311
312 return srv;
313}
314
315////////////////////////////////////////////////////////////////////////////////
316//// Local Classes
317
318class AsyncCloseConnection final : public Runnable {
319 public:
320 AsyncCloseConnection(Connection* aConnection, sqlite3* aNativeConnection,
321 nsIRunnable* aCallbackEvent)
322 : Runnable("storage::AsyncCloseConnection"),
323 mConnection(aConnection),
324 mNativeConnection(aNativeConnection),
325 mCallbackEvent(aCallbackEvent) {}
326
327 NS_IMETHODvirtual nsresult Run() override {
328 // Make sure we don't dispatch to the current thread.
329 MOZ_ASSERT(!IsOnCurrentSerialEventTarget(mConnection->eventTargetOpenedOn))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsOnCurrentSerialEventTarget(mConnection->eventTargetOpenedOn
))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!IsOnCurrentSerialEventTarget(mConnection->eventTargetOpenedOn
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!IsOnCurrentSerialEventTarget(mConnection->eventTargetOpenedOn)"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 329); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsOnCurrentSerialEventTarget(mConnection->eventTargetOpenedOn)"
")"); do { *((volatile int*)__null) = 329; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
330
331 nsCOMPtr<nsIRunnable> event =
332 NewRunnableMethod("storage::Connection::shutdownAsyncThread",
333 mConnection, &Connection::shutdownAsyncThread);
334 MOZ_ALWAYS_SUCCEEDS(NS_DispatchToMainThread(event))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(NS_DispatchToMainThread(event))), 1)))), 1))) { } else { do {
do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(NS_DispatchToMainThread(event))"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 334); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(NS_DispatchToMainThread(event))"
")"); do { *((volatile int*)__null) = 334; __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
335
336 // Internal close.
337 (void)mConnection->internalClose(mNativeConnection);
338
339 // Callback
340 if (mCallbackEvent) {
341 nsCOMPtr<nsIThread> thread;
342 (void)NS_GetMainThread(getter_AddRefs(thread));
343 (void)thread->Dispatch(mCallbackEvent, NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL);
344 }
345
346 return NS_OK;
347 }
348
349 ~AsyncCloseConnection() override {
350 NS_ReleaseOnMainThread("AsyncCloseConnection::mConnection",
351 mConnection.forget());
352 NS_ReleaseOnMainThread("AsyncCloseConnection::mCallbackEvent",
353 mCallbackEvent.forget());
354 }
355
356 private:
357 RefPtr<Connection> mConnection;
358 sqlite3* mNativeConnection;
359 nsCOMPtr<nsIRunnable> mCallbackEvent;
360};
361
362/**
363 * An event used to initialize the clone of a connection.
364 *
365 * Must be executed on the clone's async execution thread.
366 */
367class AsyncInitializeClone final : public Runnable {
368 public:
369 /**
370 * @param aConnection The connection being cloned.
371 * @param aClone The clone.
372 * @param aReadOnly If |true|, the clone is read only.
373 * @param aCallback A callback to trigger once initialization
374 * is complete. This event will be called on
375 * aClone->eventTargetOpenedOn.
376 */
377 AsyncInitializeClone(Connection* aConnection, Connection* aClone,
378 const bool aReadOnly,
379 mozIStorageCompletionCallback* aCallback)
380 : Runnable("storage::AsyncInitializeClone"),
381 mConnection(aConnection),
382 mClone(aClone),
383 mReadOnly(aReadOnly),
384 mCallback(aCallback) {
385 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 385); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 385; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
386 }
387
388 NS_IMETHODvirtual nsresult Run() override {
389 MOZ_ASSERT(!NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!NS_IsMainThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 389); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 389; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
390 nsresult rv = mConnection->initializeClone(mClone, mReadOnly);
391 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
392 return Dispatch(rv, nullptr);
393 }
394 return Dispatch(NS_OK,
395 NS_ISUPPORTS_CAST(mozIStorageAsyncConnection*, mClone)static_cast<nsISupports*>(static_cast<mozIStorageAsyncConnection
*>(mClone))
);
396 }
397
398 private:
399 nsresult Dispatch(nsresult aResult, nsISupports* aValue) {
400 RefPtr<CallbackComplete> event =
401 new CallbackComplete(aResult, aValue, mCallback.forget());
402 return mClone->eventTargetOpenedOn->Dispatch(event, NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL);
403 }
404
405 ~AsyncInitializeClone() override {
406 nsCOMPtr<nsIThread> thread;
407 DebugOnly<nsresult> rv = NS_GetMainThread(getter_AddRefs(thread));
408 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 408); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { *((volatile int*)__null) = 408; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
409
410 // Handle ambiguous nsISupports inheritance.
411 NS_ProxyRelease("AsyncInitializeClone::mConnection", thread,
412 mConnection.forget());
413 NS_ProxyRelease("AsyncInitializeClone::mClone", thread, mClone.forget());
414
415 // Generally, the callback will be released by CallbackComplete.
416 // However, if for some reason Run() is not executed, we still
417 // need to ensure that it is released here.
418 NS_ProxyRelease("AsyncInitializeClone::mCallback", thread,
419 mCallback.forget());
420 }
421
422 RefPtr<Connection> mConnection;
423 RefPtr<Connection> mClone;
424 const bool mReadOnly;
425 nsCOMPtr<mozIStorageCompletionCallback> mCallback;
426};
427
428/**
429 * A listener for async connection closing.
430 */
431class CloseListener final : public mozIStorageCompletionCallback {
432 public:
433 NS_DECL_ISUPPORTSpublic: virtual nsresult QueryInterface(const nsIID& aIID
, void** aInstancePtr) override; virtual MozExternalRefCountType
AddRef(void) override; virtual MozExternalRefCountType Release
(void) override; using HasThreadSafeRefCnt = std::false_type;
protected: nsAutoRefCnt mRefCnt; nsAutoOwningThread _mOwningThread
; public:
434 CloseListener() : mClosed(false) {}
435
436 NS_IMETHODvirtual nsresult Complete(nsresult, nsISupports*) override {
437 mClosed = true;
438 return NS_OK;
439 }
440
441 bool mClosed;
442
443 private:
444 ~CloseListener() = default;
445};
446
447NS_IMPL_ISUPPORTS(CloseListener, mozIStorageCompletionCallback)MozExternalRefCountType CloseListener::AddRef(void) { static_assert
(!std::is_destructible_v<CloseListener>, "Reference-counted class "
"CloseListener" " should not have a public destructor. " "Make this class's destructor non-public"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 447); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
447; __attribute__((nomerge)) ::abort(); } while (false); } }
while (false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("CloseListener" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("CloseListener" != nullptr))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("\"CloseListener\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 447); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"CloseListener\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 447; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("CloseListener" " not thread-safe"); nsrefcnt
count = ++mRefCnt; NS_LogAddRef((this), (count), ("CloseListener"
), (uint32_t)(sizeof(*this))); return count; } MozExternalRefCountType
CloseListener::Release(void) { do { static_assert( mozilla::
detail::AssertionConditionType<decltype(int32_t(mRefCnt) >
0)>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(int32_t(mRefCnt) > 0))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("int32_t(mRefCnt) > 0" " (" "dup release"
")", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 447); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) > 0"
") (" "dup release" ")"); do { *((volatile int*)__null) = 447
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("CloseListener" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("CloseListener" != nullptr))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("\"CloseListener\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 447); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"CloseListener\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 447; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("CloseListener" " not thread-safe"); const char
* const nametmp = "CloseListener"; nsrefcnt count = --mRefCnt
; NS_LogRelease((this), (count), (nametmp)); if (count == 0) {
mRefCnt = 1; delete (this); return 0; } return count; } nsresult
CloseListener::QueryInterface(const nsIID& aIID, void** aInstancePtr
) { do { if (!(aInstancePtr)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "QueryInterface requires a non-NULL destination!", "aInstancePtr"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 447); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(1 > 0, "Need more arguments to NS_INTERFACE_TABLE"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<CloseListener, mozIStorageCompletionCallback
>, int32_t( reinterpret_cast<char*>(static_cast<mozIStorageCompletionCallback
*>((CloseListener*)0x1000)) - reinterpret_cast<char*>
((CloseListener*)0x1000))}, {&mozilla::detail::kImplementedIID
<CloseListener, nsISupports>, int32_t(reinterpret_cast<
char*>(static_cast<nsISupports*>( static_cast<mozIStorageCompletionCallback
*>((CloseListener*)0x1000))) - reinterpret_cast<char*>
((CloseListener*)0x1000))}, { nullptr, 0 } } ; static_assert(
std::size(table) > 1, "need at least 1 interface"); rv = NS_TableDrivenQI
(static_cast<void*>(this), aIID, aInstancePtr, table); return
rv; }
448
449class AsyncVacuumEvent final : public Runnable {
450 public:
451 AsyncVacuumEvent(Connection* aConnection,
452 mozIStorageCompletionCallback* aCallback,
453 bool aUseIncremental, int32_t aSetPageSize)
454 : Runnable("storage::AsyncVacuum"),
455 mConnection(aConnection),
456 mCallback(aCallback),
457 mUseIncremental(aUseIncremental),
458 mSetPageSize(aSetPageSize),
459 mStatus(NS_ERROR_UNEXPECTED) {}
460
461 NS_IMETHODvirtual nsresult Run() override {
462 // This is initially dispatched to the helper thread, then re-dispatched
463 // to the opener thread, where it will callback.
464 if (IsOnCurrentSerialEventTarget(mConnection->eventTargetOpenedOn)) {
465 // Send the completion event.
466 if (mCallback) {
467 mozilla::Unused << mCallback->Complete(mStatus, nullptr);
468 }
469 return NS_OK;
470 }
471
472 // Ensure to invoke the callback regardless of errors.
473 auto guard = MakeScopeExit([&]() {
474 mConnection->mIsStatementOnHelperThreadInterruptible = false;
475 mozilla::Unused << mConnection->eventTargetOpenedOn->Dispatch(
476 this, NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL);
477 });
478
479 // Get list of attached databases.
480 nsCOMPtr<mozIStorageStatement> stmt;
481 nsresult rv = mConnection->CreateStatement(MOZ_STORAGE_UNIQUIFY_QUERY_STR"/* " "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
" */ "
482 "PRAGMA database_list"_ns,
483 getter_AddRefs(stmt));
484 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 484); return rv; } } while (false)
;
485 // We must accumulate names and loop through them later, otherwise VACUUM
486 // will see an ongoing statement and bail out.
487 nsTArray<nsCString> schemaNames;
488 bool hasResult = false;
489 while (stmt && NS_SUCCEEDED(stmt->ExecuteStep(&hasResult))((bool)(__builtin_expect(!!(!NS_FAILED_impl(stmt->ExecuteStep
(&hasResult))), 1)))
&& hasResult) {
490 nsAutoCString name;
491 rv = stmt->GetUTF8String(1, name);
492 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !name.EqualsLiteral("temp")) {
493 schemaNames.AppendElement(name);
494 }
495 }
496 mStatus = NS_OK;
497 // Mark this vacuum as an interruptible operation, so it can be interrupted
498 // if the connection closes during shutdown.
499 mConnection->mIsStatementOnHelperThreadInterruptible = true;
500 for (const nsCString& schemaName : schemaNames) {
501 rv = this->Vacuum(schemaName);
502 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
503 // This is sub-optimal since it's only keeping the last error reason,
504 // but it will do for now.
505 mStatus = rv;
506 }
507 }
508 return mStatus;
509 }
510
511 nsresult Vacuum(const nsACString& aSchemaName) {
512 // Abort if we're in shutdown.
513 if (AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownConfirmed)) {
514 return NS_ERROR_ABORT;
515 }
516 int32_t removablePages = mConnection->RemovablePagesInFreeList(aSchemaName);
517 if (!removablePages) {
518 // There's no empty pages to remove, so skip this vacuum for now.
519 return NS_OK;
520 }
521 nsresult rv;
522 bool needsFullVacuum = true;
523
524 if (mSetPageSize) {
525 nsAutoCString query(MOZ_STORAGE_UNIQUIFY_QUERY_STR"/* " "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
" */ "
"PRAGMA ");
526 query.Append(aSchemaName);
527 query.AppendLiteral(".page_size = ");
528 query.AppendInt(mSetPageSize);
529 nsCOMPtr<mozIStorageStatement> stmt;
530 rv = mConnection->ExecuteSimpleSQL(query);
531 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 531); return rv; } } while (false)
;
532 }
533
534 // Check auto_vacuum.
535 {
536 nsAutoCString query(MOZ_STORAGE_UNIQUIFY_QUERY_STR"/* " "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
" */ "
"PRAGMA ");
537 query.Append(aSchemaName);
538 query.AppendLiteral(".auto_vacuum");
539 nsCOMPtr<mozIStorageStatement> stmt;
540 rv = mConnection->CreateStatement(query, getter_AddRefs(stmt));
541 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 541); return rv; } } while (false)
;
542 bool hasResult = false;
543 bool changeAutoVacuum = false;
544 if (stmt && NS_SUCCEEDED(stmt->ExecuteStep(&hasResult))((bool)(__builtin_expect(!!(!NS_FAILED_impl(stmt->ExecuteStep
(&hasResult))), 1)))
&& hasResult) {
545 bool isIncrementalVacuum = stmt->AsInt32(0) == 2;
546 changeAutoVacuum = isIncrementalVacuum != mUseIncremental;
547 if (isIncrementalVacuum && !changeAutoVacuum) {
548 needsFullVacuum = false;
549 }
550 }
551 // Changing auto_vacuum is only supported on the main schema.
552 if (aSchemaName.EqualsLiteral("main") && changeAutoVacuum) {
553 nsAutoCString query(MOZ_STORAGE_UNIQUIFY_QUERY_STR"/* " "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
" */ "
"PRAGMA ");
554 query.Append(aSchemaName);
555 query.AppendLiteral(".auto_vacuum = ");
556 query.AppendInt(mUseIncremental ? 2 : 0);
557 rv = mConnection->ExecuteSimpleSQL(query);
558 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 558); return rv; } } while (false)
;
559 }
560 }
561
562 if (needsFullVacuum) {
563 nsAutoCString query(MOZ_STORAGE_UNIQUIFY_QUERY_STR"/* " "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
" */ "
"VACUUM ");
564 query.Append(aSchemaName);
565 rv = mConnection->ExecuteSimpleSQL(query);
566 // TODO (Bug 1818039): Report failed vacuum telemetry.
567 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 567); return rv; } } while (false)
;
568 } else {
569 nsAutoCString query(MOZ_STORAGE_UNIQUIFY_QUERY_STR"/* " "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
" */ "
"PRAGMA ");
570 query.Append(aSchemaName);
571 query.AppendLiteral(".incremental_vacuum(");
572 query.AppendInt(removablePages);
573 query.AppendLiteral(")");
574 rv = mConnection->ExecuteSimpleSQL(query);
575 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 575); return rv; } } while (false)
;
576 }
577
578 return NS_OK;
579 }
580
581 ~AsyncVacuumEvent() override {
582 NS_ReleaseOnMainThread("AsyncVacuum::mConnection", mConnection.forget());
583 NS_ReleaseOnMainThread("AsyncVacuum::mCallback", mCallback.forget());
584 }
585
586 private:
587 RefPtr<Connection> mConnection;
588 nsCOMPtr<mozIStorageCompletionCallback> mCallback;
589 bool mUseIncremental;
590 int32_t mSetPageSize;
591 Atomic<nsresult> mStatus;
592};
593
594/**
595 * A runnable to perform an SQLite database backup when there may be one or more
596 * open connections on that database.
597 */
598class AsyncBackupDatabaseFile final : public Runnable, public nsITimerCallback {
599 public:
600 NS_DECL_ISUPPORTS_INHERITEDpublic: virtual nsresult QueryInterface(const nsIID& aIID
, void** aInstancePtr) override; virtual MozExternalRefCountType
AddRef(void) override; virtual MozExternalRefCountType Release
(void) override;
601
602 /**
603 * @param aConnection The connection to the database being backed up.
604 * @param aNativeConnection The native connection to the database being backed
605 * up.
606 * @param aDestinationFile The destination file for the created backup.
607 * @param aCallback A callback to trigger once the backup process has
608 * completed. The callback will be supplied with an nsresult
609 * indicating whether or not the backup was successfully
610 * created. This callback will be called on the
611 * mConnection->eventTargetOpenedOn thread.
612 * @throws
613 */
614 AsyncBackupDatabaseFile(Connection* aConnection, sqlite3* aNativeConnection,
615 nsIFile* aDestinationFile,
616 mozIStorageCompletionCallback* aCallback,
617 int32_t aPagesPerStep, uint32_t aStepDelayMs)
618 : Runnable("storage::AsyncBackupDatabaseFile"),
619 mConnection(aConnection),
620 mNativeConnection(aNativeConnection),
621 mDestinationFile(aDestinationFile),
622 mCallback(aCallback),
623 mPagesPerStep(aPagesPerStep),
624 mStepDelayMs(aStepDelayMs),
625 mBackupFile(nullptr),
626 mBackupHandle(nullptr) {
627 MOZ_ASSERT(NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("NS_IsMainThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 627); AnnotateMozCrashReason("MOZ_ASSERT" "(" "NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 627; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
628 }
629
630 NS_IMETHODvirtual nsresult Run() override {
631 MOZ_ASSERT(!NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!NS_IsMainThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 631); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 631; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
632
633 nsAutoString path;
634 nsresult rv = mDestinationFile->GetPath(path);
635 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
636 return Dispatch(rv, nullptr);
637 }
638 // Put a .tmp on the end of the destination while the backup is underway.
639 // This extension will be stripped off after the backup successfully
640 // completes.
641 path.AppendLiteral(".tmp");
642
643 int srv = ::sqlite3_open(NS_ConvertUTF16toUTF8(path).get(), &mBackupFile);
644 if (srv != SQLITE_OK0) {
645 return Dispatch(NS_ERROR_FAILURE, nullptr);
646 }
647
648 static const char* mainDBName = "main";
649
650 mBackupHandle = ::sqlite3_backup_init(mBackupFile, mainDBName,
651 mNativeConnection, mainDBName);
652 if (!mBackupHandle) {
653 MOZ_ALWAYS_TRUE(::sqlite3_close(mBackupFile) == SQLITE_OK)do { if ((__builtin_expect(!!(::sqlite3_close(mBackupFile) ==
0), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "::sqlite3_close(mBackupFile) == SQLITE_OK", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 653); AnnotateMozCrashReason("MOZ_CRASH(" "::sqlite3_close(mBackupFile) == SQLITE_OK"
")"); do { *((volatile int*)__null) = 653; __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
654 return Dispatch(NS_ERROR_FAILURE, nullptr);
655 }
656
657 return DoStep();
658 }
659
660 NS_IMETHODvirtual nsresult
661 Notify(nsITimer* aTimer) override { return DoStep(); }
662
663 private:
664 nsresult DoStep() {
665#define DISPATCH_AND_RETURN_IF_FAILED(rv) \
666 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) { \
667 return Dispatch(rv, nullptr); \
668 }
669
670 // This guard is used to close the backup database in the event of
671 // some failure throughout this process. We release the exit guard
672 // only if we complete the backup successfully, or defer to another
673 // later call to DoStep.
674 auto guard = MakeScopeExit([&]() {
675 MOZ_ALWAYS_TRUE(::sqlite3_close(mBackupFile) == SQLITE_OK)do { if ((__builtin_expect(!!(::sqlite3_close(mBackupFile) ==
0), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "::sqlite3_close(mBackupFile) == SQLITE_OK", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 675); AnnotateMozCrashReason("MOZ_CRASH(" "::sqlite3_close(mBackupFile) == SQLITE_OK"
")"); do { *((volatile int*)__null) = 675; __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
676 mBackupFile = nullptr;
677 });
678
679 MOZ_ASSERT(!NS_IsMainThread())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!NS_IsMainThread())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!NS_IsMainThread()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("!NS_IsMainThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 679); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!NS_IsMainThread()"
")"); do { *((volatile int*)__null) = 679; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
680 nsAutoString originalPath;
681 nsresult rv = mDestinationFile->GetPath(originalPath);
682 DISPATCH_AND_RETURN_IF_FAILED(rv);
683
684 nsAutoString tempPath = originalPath;
685 tempPath.AppendLiteral(".tmp");
686
687 nsCOMPtr<nsIFile> file;
688 rv = NS_NewLocalFile(tempPath, getter_AddRefs(file));
689 DISPATCH_AND_RETURN_IF_FAILED(rv);
690
691 int srv = ::sqlite3_backup_step(mBackupHandle, mPagesPerStep);
692 if (srv == SQLITE_OK0 || srv == SQLITE_BUSY5 || srv == SQLITE_LOCKED6) {
693 // We're continuing the backup later. Release the guard to avoid closing
694 // the database.
695 guard.release();
696 // Queue up the next step
697 return NS_NewTimerWithCallback(getter_AddRefs(mTimer), this, mStepDelayMs,
698 nsITimer::TYPE_ONE_SHOT,
699 GetCurrentSerialEventTarget());
700 }
701#ifdef DEBUG1
702 if (srv != SQLITE_DONE101) {
703 nsCString warnMsg;
704 warnMsg.AppendLiteral(
705 "The SQLite database copy could not be completed due to an error: ");
706 warnMsg.Append(::sqlite3_errmsg(mBackupFile));
707 NS_WARNING(warnMsg.get())NS_DebugBreak(NS_DEBUG_WARNING, warnMsg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 707)
;
708 }
709#endif
710
711 (void)::sqlite3_backup_finish(mBackupHandle);
712 MOZ_ALWAYS_TRUE(::sqlite3_close(mBackupFile) == SQLITE_OK)do { if ((__builtin_expect(!!(::sqlite3_close(mBackupFile) ==
0), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "::sqlite3_close(mBackupFile) == SQLITE_OK", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 712); AnnotateMozCrashReason("MOZ_CRASH(" "::sqlite3_close(mBackupFile) == SQLITE_OK"
")"); do { *((volatile int*)__null) = 712; __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
713 mBackupFile = nullptr;
714
715 // The database is already closed, so we can release this guard now.
716 guard.release();
717
718 if (srv != SQLITE_DONE101) {
719 NS_WARNING("Failed to create database copy.")NS_DebugBreak(NS_DEBUG_WARNING, "Failed to create database copy."
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 719)
;
720
721 // The partially created database file is not useful. Let's remove it.
722 rv = file->Remove(false);
723 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
724 NS_WARNING(NS_DebugBreak(NS_DEBUG_WARNING, "Removing a partially backed up SQLite database file failed."
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 725)
725 "Removing a partially backed up SQLite database file failed.")NS_DebugBreak(NS_DEBUG_WARNING, "Removing a partially backed up SQLite database file failed."
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 725)
;
726 }
727
728 return Dispatch(convertResultCode(srv), nullptr);
729 }
730
731 // Now that we've successfully created the copy, we'll strip off the .tmp
732 // extension.
733
734 nsAutoString leafName;
735 rv = mDestinationFile->GetLeafName(leafName);
736 DISPATCH_AND_RETURN_IF_FAILED(rv);
737
738 rv = file->RenameTo(nullptr, leafName);
739 DISPATCH_AND_RETURN_IF_FAILED(rv);
740
741#undef DISPATCH_AND_RETURN_IF_FAILED
742 return Dispatch(NS_OK, nullptr);
743 }
744
745 nsresult Dispatch(nsresult aResult, nsISupports* aValue) {
746 RefPtr<CallbackComplete> event =
747 new CallbackComplete(aResult, aValue, mCallback.forget());
748 return mConnection->eventTargetOpenedOn->Dispatch(event,
749 NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL);
750 }
751
752 ~AsyncBackupDatabaseFile() override {
753 nsresult rv;
754 nsCOMPtr<nsIThread> thread =
755 do_QueryInterface(mConnection->eventTargetOpenedOn, &rv);
756 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 756); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { *((volatile int*)__null) = 756; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
757
758 // Handle ambiguous nsISupports inheritance.
759 NS_ProxyRelease("AsyncBackupDatabaseFile::mConnection", thread,
760 mConnection.forget());
761 NS_ProxyRelease("AsyncBackupDatabaseFile::mDestinationFile", thread,
762 mDestinationFile.forget());
763
764 // Generally, the callback will be released by CallbackComplete.
765 // However, if for some reason Run() is not executed, we still
766 // need to ensure that it is released here.
767 NS_ProxyRelease("AsyncInitializeClone::mCallback", thread,
768 mCallback.forget());
769 }
770
771 RefPtr<Connection> mConnection;
772 sqlite3* mNativeConnection;
773 nsCOMPtr<nsITimer> mTimer;
774 nsCOMPtr<nsIFile> mDestinationFile;
775 nsCOMPtr<mozIStorageCompletionCallback> mCallback;
776 int32_t mPagesPerStep;
777 uint32_t mStepDelayMs;
778 sqlite3* mBackupFile;
779 sqlite3_backup* mBackupHandle;
780};
781
782NS_IMPL_ISUPPORTS_INHERITED(AsyncBackupDatabaseFile, Runnable, nsITimerCallback)nsresult AsyncBackupDatabaseFile::QueryInterface(const nsIID&
aIID, void** aInstancePtr) { do { if (!(aInstancePtr)) { NS_DebugBreak
(NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 782); MOZ_PretendNoReturn(); } } while (0); nsresult rv = NS_ERROR_FAILURE
; static_assert(1 > 0, "Need more arguments to NS_INTERFACE_TABLE_INHERITED"
); static const QITableEntry table[] = { {&mozilla::detail
::kImplementedIID<AsyncBackupDatabaseFile, nsITimerCallback
>, int32_t( reinterpret_cast<char*>(static_cast<nsITimerCallback
*>((AsyncBackupDatabaseFile*)0x1000)) - reinterpret_cast<
char*>((AsyncBackupDatabaseFile*)0x1000))}, { nullptr, 0 }
} ; static_assert(std::size(table) > 1, "need at least 1 interface"
); rv = NS_TableDrivenQI(static_cast<void*>(this), aIID
, aInstancePtr, table); if (((bool)(__builtin_expect(!!(!NS_FAILED_impl
(rv)), 1)))) return rv; return Runnable::QueryInterface(aIID,
aInstancePtr); } MozExternalRefCountType AsyncBackupDatabaseFile
::AddRef(void) { static_assert(!std::is_destructible_v<AsyncBackupDatabaseFile
>, "Reference-counted class " "AsyncBackupDatabaseFile" " should not have a public destructor. "
"Make this class's destructor non-public"); nsrefcnt r = Runnable
::AddRef(); if constexpr (::mozilla::detail::ShouldLogInheritedRefcnt
<AsyncBackupDatabaseFile>) { NS_LogAddRef((this), (r), (
"AsyncBackupDatabaseFile"), (uint32_t)(sizeof(*this))); } return
r; } MozExternalRefCountType AsyncBackupDatabaseFile::Release
(void) { nsrefcnt r = Runnable::Release(); if constexpr (::mozilla
::detail::ShouldLogInheritedRefcnt<AsyncBackupDatabaseFile
>) { NS_LogRelease((this), (r), ("AsyncBackupDatabaseFile"
)); } return r; }
783
784} // namespace
785
786////////////////////////////////////////////////////////////////////////////////
787//// Connection
788
789Connection::Connection(Service* aService, int aFlags,
790 ConnectionOperation aSupportedOperations,
791 const nsCString& aTelemetryFilename, bool aInterruptible,
792 bool aIgnoreLockingMode, bool aOpenNotExclusive)
793 : sharedAsyncExecutionMutex("Connection::sharedAsyncExecutionMutex"),
794 sharedDBMutex("Connection::sharedDBMutex"),
795 eventTargetOpenedOn(WrapNotNull(GetCurrentSerialEventTarget())),
796 mIsStatementOnHelperThreadInterruptible(false),
797 mDBConn(nullptr),
798 mDefaultTransactionType(mozIStorageConnection::TRANSACTION_DEFERRED),
799 mDestroying(false),
800 mProgressHandler(nullptr),
801 mStorageService(aService),
802 mFlags(aFlags),
803 mTransactionNestingLevel(0),
804 mSupportedOperations(aSupportedOperations),
805 mInterruptible(aSupportedOperations == Connection::ASYNCHRONOUS ||
806 aInterruptible),
807 mIgnoreLockingMode(aIgnoreLockingMode),
808 mOpenNotExclusive(aOpenNotExclusive),
809 mAsyncExecutionThreadShuttingDown(false),
810 mConnectionClosed(false),
811 mGrowthChunkSize(0) {
812 MOZ_ASSERT(!mIgnoreLockingMode || mFlags & SQLITE_OPEN_READONLY,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mIgnoreLockingMode || mFlags & 0x00000001)>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!mIgnoreLockingMode || mFlags & 0x00000001))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("!mIgnoreLockingMode || mFlags & 0x00000001"
" (" "Can't ignore locking for a non-readonly connection!" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 813); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIgnoreLockingMode || mFlags & 0x00000001"
") (" "Can't ignore locking for a non-readonly connection!" ")"
); do { *((volatile int*)__null) = 813; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
813 "Can't ignore locking for a non-readonly connection!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mIgnoreLockingMode || mFlags & 0x00000001)>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!mIgnoreLockingMode || mFlags & 0x00000001))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("!mIgnoreLockingMode || mFlags & 0x00000001"
" (" "Can't ignore locking for a non-readonly connection!" ")"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 813); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIgnoreLockingMode || mFlags & 0x00000001"
") (" "Can't ignore locking for a non-readonly connection!" ")"
); do { *((volatile int*)__null) = 813; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
814 mStorageService->registerConnection(this);
815 MOZ_ASSERT(!aTelemetryFilename.IsEmpty(),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aTelemetryFilename.IsEmpty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aTelemetryFilename.IsEmpty(
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!aTelemetryFilename.IsEmpty()" " (" "A telemetry filename should have been passed-in."
")", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 816); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aTelemetryFilename.IsEmpty()"
") (" "A telemetry filename should have been passed-in." ")"
); do { *((volatile int*)__null) = 816; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
816 "A telemetry filename should have been passed-in.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!aTelemetryFilename.IsEmpty())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aTelemetryFilename.IsEmpty(
)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!aTelemetryFilename.IsEmpty()" " (" "A telemetry filename should have been passed-in."
")", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 816); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aTelemetryFilename.IsEmpty()"
") (" "A telemetry filename should have been passed-in." ")"
); do { *((volatile int*)__null) = 816; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
817 mTelemetryFilename.Assign(aTelemetryFilename);
818}
819
820Connection::~Connection() {
821 // Failsafe Close() occurs in our custom Release method because of
822 // complications related to Close() potentially invoking AsyncClose() which
823 // will increment our refcount.
824 MOZ_ASSERT(!mAsyncExecutionThread,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mAsyncExecutionThread)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mAsyncExecutionThread))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("!mAsyncExecutionThread"
" (" "The async thread has not been shutdown properly!" ")",
"/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 825); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mAsyncExecutionThread"
") (" "The async thread has not been shutdown properly!" ")"
); do { *((volatile int*)__null) = 825; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
825 "The async thread has not been shutdown properly!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mAsyncExecutionThread)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mAsyncExecutionThread))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("!mAsyncExecutionThread"
" (" "The async thread has not been shutdown properly!" ")",
"/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 825); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mAsyncExecutionThread"
") (" "The async thread has not been shutdown properly!" ")"
); do { *((volatile int*)__null) = 825; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
826}
827
828NS_IMPL_ADDREF(Connection)MozExternalRefCountType Connection::AddRef(void) { static_assert
(!std::is_destructible_v<Connection>, "Reference-counted class "
"Connection" " should not have a public destructor. " "Make this class's destructor non-public"
); do { static_assert( mozilla::detail::AssertionConditionType
<decltype(int32_t(mRefCnt) >= 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(int32_t(mRefCnt) >= 0))),
0))) { do { } while (false); MOZ_ReportAssertionFailure("int32_t(mRefCnt) >= 0"
" (" "illegal refcnt" ")", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 828); AnnotateMozCrashReason("MOZ_ASSERT" "(" "int32_t(mRefCnt) >= 0"
") (" "illegal refcnt" ")"); do { *((volatile int*)__null) =
828; __attribute__((nomerge)) ::abort(); } while (false); } }
while (false); do { static_assert( mozilla::detail::AssertionConditionType
<decltype("Connection" != nullptr)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!("Connection" != nullptr))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("\"Connection\" != nullptr"
" (" "Must specify a name" ")", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 828); AnnotateMozCrashReason("MOZ_ASSERT" "(" "\"Connection\" != nullptr"
") (" "Must specify a name" ")"); do { *((volatile int*)__null
) = 828; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false); if (!mRefCnt.isThreadSafe) _mOwningThread
.AssertOwnership("Connection" " not thread-safe"); nsrefcnt count
= ++mRefCnt; NS_LogAddRef((this), (count), ("Connection"), (
uint32_t)(sizeof(*this))); return count; }
829
830NS_INTERFACE_MAP_BEGIN(Connection)nsresult Connection::QueryInterface(const nsIID& aIID, void
** aInstancePtr) { do { if (!(aInstancePtr)) { NS_DebugBreak(
NS_DEBUG_ASSERTION, "QueryInterface requires a non-NULL destination!"
, "aInstancePtr", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 830); MOZ_PretendNoReturn(); } } while (0); nsISupports* foundInterface
;
831 NS_INTERFACE_MAP_ENTRY(mozIStorageAsyncConnection)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, mozIStorageAsyncConnection>)) foundInterface
= static_cast<mozIStorageAsyncConnection*>(this); else
832 NS_INTERFACE_MAP_ENTRY(nsIInterfaceRequestor)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsIInterfaceRequestor>)) foundInterface
= static_cast<nsIInterfaceRequestor*>(this); else
833 NS_INTERFACE_MAP_ENTRY(mozIStorageConnection)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, mozIStorageConnection>)) foundInterface
= static_cast<mozIStorageConnection*>(this); else
834 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, mozIStorageConnection)if (aIID.Equals(mozilla::detail::kImplementedIID<std::remove_reference_t
<decltype(*this)>, nsISupports>)) foundInterface = static_cast
<nsISupports*>(static_cast<mozIStorageConnection*>
(this)); else
835NS_INTERFACE_MAP_ENDfoundInterface = 0; nsresult status; if (!foundInterface) { do
{ static_assert( mozilla::detail::AssertionConditionType<
decltype(!aIID.Equals((nsISupports::COMTypeInfo<nsISupports
, void>::kIID)))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!aIID.Equals((nsISupports::COMTypeInfo
<nsISupports, void>::kIID))))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("!aIID.Equals((nsISupports::COMTypeInfo<nsISupports, void>::kIID))"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 835); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!aIID.Equals((nsISupports::COMTypeInfo<nsISupports, void>::kIID))"
")"); do { *((volatile int*)__null) = 835; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); status = NS_NOINTERFACE
; } else { (foundInterface)->AddRef(); status = NS_OK; } *
aInstancePtr = foundInterface; return status; }
836
837// This is identical to what NS_IMPL_RELEASE provides, but with the
838// extra |1 == count| case.
839NS_IMETHODIMP_(MozExternalRefCountType)MozExternalRefCountType Connection::Release(void) {
840 MOZ_ASSERT(0 != mRefCnt, "dup release")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(0 != mRefCnt)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(0 != mRefCnt))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("0 != mRefCnt" " ("
"dup release" ")", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 840); AnnotateMozCrashReason("MOZ_ASSERT" "(" "0 != mRefCnt"
") (" "dup release" ")"); do { *((volatile int*)__null) = 840
; __attribute__((nomerge)) ::abort(); } while (false); } } while
(false)
;
841 nsrefcnt count = --mRefCnt;
842 NS_LOG_RELEASE(this, count, "Connection")NS_LogRelease((this), (count), ("Connection"));
843 if (1 == count) {
844 // If the refcount went to 1, the single reference must be from
845 // gService->mConnections (in class |Service|). And the code calling
846 // Release is either:
847 // - The "user" code that had created the connection, releasing on any
848 // thread.
849 // - One of Service's getConnections() callers had acquired a strong
850 // reference to the Connection that out-lived the last "user" reference,
851 // and now that just got dropped. Note that this reference could be
852 // getting dropped on the main thread or Connection->eventTargetOpenedOn
853 // (because of the NewRunnableMethod used by minimizeMemory).
854 //
855 // Either way, we should now perform our failsafe Close() and unregister.
856 // However, we only want to do this once, and the reality is that our
857 // refcount could go back up above 1 and down again at any time if we are
858 // off the main thread and getConnections() gets called on the main thread,
859 // so we use an atomic here to do this exactly once.
860 if (mDestroying.compareExchange(false, true)) {
861 // Close the connection, dispatching to the opening event target if we're
862 // not on that event target already and that event target is still
863 // accepting runnables. We do this because it's possible we're on the main
864 // thread because of getConnections(), and we REALLY don't want to
865 // transfer I/O to the main thread if we can avoid it.
866 if (IsOnCurrentSerialEventTarget(eventTargetOpenedOn)) {
867 // This could cause SpinningSynchronousClose() to be invoked and AddRef
868 // triggered for AsyncCloseConnection's strong ref if the conn was ever
869 // use for async purposes. (Main-thread only, though.)
870 Unused << synchronousClose();
871 } else {
872 nsCOMPtr<nsIRunnable> event =
873 NewRunnableMethod("storage::Connection::synchronousClose", this,
874 &Connection::synchronousClose);
875 if (NS_FAILED(eventTargetOpenedOn->Dispatch(event.forget(),((bool)(__builtin_expect(!!(NS_FAILED_impl(eventTargetOpenedOn
->Dispatch(event.forget(), nsIEventTarget::DISPATCH_NORMAL
))), 0)))
876 NS_DISPATCH_NORMAL))((bool)(__builtin_expect(!!(NS_FAILED_impl(eventTargetOpenedOn
->Dispatch(event.forget(), nsIEventTarget::DISPATCH_NORMAL
))), 0)))
) {
877 // The event target was dead and so we've just leaked our runnable.
878 // This should not happen because our non-main-thread consumers should
879 // be explicitly closing their connections, not relying on us to close
880 // them for them. (It's okay to let a statement go out of scope for
881 // automatic cleanup, but not a Connection.)
882 MOZ_ASSERT(false,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "Leaked Connection::synchronousClose(), ownership fail."
")", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 883); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"Leaked Connection::synchronousClose(), ownership fail." ")"
); do { *((volatile int*)__null) = 883; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
883 "Leaked Connection::synchronousClose(), ownership fail.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "Leaked Connection::synchronousClose(), ownership fail."
")", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 883); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"Leaked Connection::synchronousClose(), ownership fail." ")"
); do { *((volatile int*)__null) = 883; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
884 Unused << synchronousClose();
885 }
886 }
887
888 // This will drop its strong reference right here, right now.
889 mStorageService->unregisterConnection(this);
890 }
891 } else if (0 == count) {
892 mRefCnt = 1; /* stabilize */
893#if 0 /* enable this to find non-threadsafe destructors: */
894 NS_ASSERT_OWNINGTHREAD(Connection)_mOwningThread.AssertOwnership("Connection" " not thread-safe"
)
;
895#endif
896 delete (this);
897 return 0;
898 }
899 return count;
900}
901
902int32_t Connection::getSqliteRuntimeStatus(int32_t aStatusOption,
903 int32_t* aMaxValue) {
904 MOZ_ASSERT(connectionReady(), "A connection must exist at this point")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(connectionReady())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(connectionReady()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("connectionReady()"
" (" "A connection must exist at this point" ")", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 904); AnnotateMozCrashReason("MOZ_ASSERT" "(" "connectionReady()"
") (" "A connection must exist at this point" ")"); do { *((
volatile int*)__null) = 904; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
905 int curr = 0, max = 0;
906 DebugOnly<int> rc =
907 ::sqlite3_db_status(mDBConn, aStatusOption, &curr, &max, 0);
908 MOZ_ASSERT(NS_SUCCEEDED(convertResultCode(rc)))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(convertResultCode
(rc))), 1))))>::isValid, "invalid assertion condition"); if
((__builtin_expect(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(convertResultCode(rc))), 1)))))), 0))) { do { } while (false
); MOZ_ReportAssertionFailure("((bool)(__builtin_expect(!!(!NS_FAILED_impl(convertResultCode(rc))), 1)))"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 908); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(convertResultCode(rc))), 1)))"
")"); do { *((volatile int*)__null) = 908; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
909 if (aMaxValue) *aMaxValue = max;
910 return curr;
911}
912
913nsIEventTarget* Connection::getAsyncExecutionTarget() {
914 NS_ENSURE_TRUE(IsOnCurrentSerialEventTarget(eventTargetOpenedOn), nullptr)do { if ((__builtin_expect(!!(!(IsOnCurrentSerialEventTarget(
eventTargetOpenedOn))), 0))) { NS_DebugBreak(NS_DEBUG_WARNING
, "NS_ENSURE_TRUE(" "IsOnCurrentSerialEventTarget(eventTargetOpenedOn)"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 914); return nullptr; } } while (false)
;
915
916 // Don't return the asynchronous event target if we are shutting down.
917 if (mAsyncExecutionThreadShuttingDown) {
918 return nullptr;
919 }
920
921 // Create the async event target if there's none yet.
922 if (!mAsyncExecutionThread) {
923 // Names start with "sqldb:" followed by a recognizable name, like the
924 // database file name, or a specially crafted name like "memory".
925 // This name will be surfaced on https://crash-stats.mozilla.org, so any
926 // sensitive part of the file name (e.g. an URL origin) should be replaced
927 // by passing an explicit telemetryName to openDatabaseWithFileURL.
928 nsAutoCString name("sqldb:"_ns);
929 name.Append(mTelemetryFilename);
930 static nsThreadPoolNaming naming;
931 nsresult rv = NS_NewNamedThread(naming.GetNextThreadName(name),
932 getter_AddRefs(mAsyncExecutionThread));
933 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
934 NS_WARNING("Failed to create async thread.")NS_DebugBreak(NS_DEBUG_WARNING, "Failed to create async thread."
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 934)
;
935 return nullptr;
936 }
937 }
938
939 return mAsyncExecutionThread;
940}
941
942void Connection::RecordOpenStatus(nsresult rv) {
943 nsCString histogramKey = mTelemetryFilename;
944
945 if (histogramKey.IsEmpty()) {
946 histogramKey.AssignLiteral("unknown");
947 }
948
949 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))) {
950 AccumulateCategoricalKeyed(histogramKey, LABELS_SQLITE_STORE_OPEN::success);
951 return;
952 }
953
954 switch (rv) {
955 case NS_ERROR_FILE_CORRUPTED:
956 AccumulateCategoricalKeyed(histogramKey,
957 LABELS_SQLITE_STORE_OPEN::corrupt);
958 break;
959 case NS_ERROR_STORAGE_IOERR:
960 AccumulateCategoricalKeyed(histogramKey,
961 LABELS_SQLITE_STORE_OPEN::diskio);
962 break;
963 case NS_ERROR_FILE_ACCESS_DENIED:
964 case NS_ERROR_FILE_IS_LOCKED:
965 case NS_ERROR_FILE_READ_ONLY:
966 AccumulateCategoricalKeyed(histogramKey,
967 LABELS_SQLITE_STORE_OPEN::access);
968 break;
969 case NS_ERROR_FILE_NO_DEVICE_SPACE:
970 AccumulateCategoricalKeyed(histogramKey,
971 LABELS_SQLITE_STORE_OPEN::diskspace);
972 break;
973 default:
974 AccumulateCategoricalKeyed(histogramKey,
975 LABELS_SQLITE_STORE_OPEN::failure);
976 }
977}
978
979void Connection::RecordQueryStatus(int srv) {
980 nsCString histogramKey = mTelemetryFilename;
981
982 if (histogramKey.IsEmpty()) {
983 histogramKey.AssignLiteral("unknown");
984 }
985
986 switch (srv) {
987 case SQLITE_OK0:
988 case SQLITE_ROW100:
989 case SQLITE_DONE101:
990
991 // Note that these are returned when we intentionally cancel a statement so
992 // they aren't indicating a failure.
993 case SQLITE_ABORT4:
994 case SQLITE_INTERRUPT9:
995 AccumulateCategoricalKeyed(histogramKey,
996 LABELS_SQLITE_STORE_QUERY::success);
997 break;
998 case SQLITE_CORRUPT11:
999 case SQLITE_NOTADB26:
1000 AccumulateCategoricalKeyed(histogramKey,
1001 LABELS_SQLITE_STORE_QUERY::corrupt);
1002 break;
1003 case SQLITE_PERM3:
1004 case SQLITE_CANTOPEN14:
1005 case SQLITE_LOCKED6:
1006 case SQLITE_READONLY8:
1007 AccumulateCategoricalKeyed(histogramKey,
1008 LABELS_SQLITE_STORE_QUERY::access);
1009 break;
1010 case SQLITE_IOERR10:
1011 case SQLITE_NOLFS22:
1012 AccumulateCategoricalKeyed(histogramKey,
1013 LABELS_SQLITE_STORE_QUERY::diskio);
1014 break;
1015 case SQLITE_FULL13:
1016 case SQLITE_TOOBIG18:
1017 AccumulateCategoricalKeyed(histogramKey,
1018 LABELS_SQLITE_STORE_QUERY::diskspace);
1019 break;
1020 case SQLITE_CONSTRAINT19:
1021 case SQLITE_RANGE25:
1022 case SQLITE_MISMATCH20:
1023 case SQLITE_MISUSE21:
1024 AccumulateCategoricalKeyed(histogramKey,
1025 LABELS_SQLITE_STORE_QUERY::misuse);
1026 break;
1027 case SQLITE_BUSY5:
1028 AccumulateCategoricalKeyed(histogramKey, LABELS_SQLITE_STORE_QUERY::busy);
1029 break;
1030 default:
1031 AccumulateCategoricalKeyed(histogramKey,
1032 LABELS_SQLITE_STORE_QUERY::failure);
1033 }
1034}
1035
1036nsresult Connection::initialize(const nsACString& aStorageKey,
1037 const nsACString& aName) {
1038 MOZ_ASSERT(aStorageKey.Equals(kMozStorageMemoryStorageKey))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aStorageKey.Equals(kMozStorageMemoryStorageKey))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(aStorageKey.Equals(kMozStorageMemoryStorageKey)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("aStorageKey.Equals(kMozStorageMemoryStorageKey)"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1038); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aStorageKey.Equals(kMozStorageMemoryStorageKey)"
")"); do { *((volatile int*)__null) = 1038; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1039 NS_ASSERTION(!connectionReady(),do { if (!(!connectionReady())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Initialize called on already opened database!", "!connectionReady()"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1040); MOZ_PretendNoReturn(); } } while (0)
1040 "Initialize called on already opened database!")do { if (!(!connectionReady())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Initialize called on already opened database!", "!connectionReady()"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1040); MOZ_PretendNoReturn(); } } while (0)
;
1041 MOZ_ASSERT(!mIgnoreLockingMode, "Can't ignore locking on an in-memory db.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!mIgnoreLockingMode)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!mIgnoreLockingMode))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("!mIgnoreLockingMode"
" (" "Can't ignore locking on an in-memory db." ")", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1041); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mIgnoreLockingMode"
") (" "Can't ignore locking on an in-memory db." ")"); do { *
((volatile int*)__null) = 1041; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
1042 AUTO_PROFILER_LABEL("Connection::initialize", OTHER)mozilla::AutoProfilerLabel raiiObject1042( "Connection::initialize"
, nullptr, JS::ProfilingCategoryPair::OTHER)
;
1043
1044 mStorageKey = aStorageKey;
1045 mName = aName;
1046
1047 // in memory database requested, sqlite uses a magic file name
1048
1049 const nsAutoCString path =
1050 mName.IsEmpty() ? nsAutoCString(":memory:"_ns)
1051 : "file:"_ns + mName + "?mode=memory&cache=shared"_ns;
1052
1053 int srv = ::sqlite3_open_v2(path.get(), &mDBConn, mFlags,
1054 basevfs::GetVFSName(true));
1055 if (srv != SQLITE_OK0) {
1056 mDBConn = nullptr;
1057 nsresult rv = convertResultCode(srv);
1058 RecordOpenStatus(rv);
1059 return rv;
1060 }
1061
1062#ifdef MOZ_SQLITE_FTS3_TOKENIZER
1063 srv =
1064 ::sqlite3_db_config(mDBConn, SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER1004, 1, 0);
1065 MOZ_ASSERT(srv == SQLITE_OK,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(srv == 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(srv == 0))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("srv == 0" " (" "SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER should be enabled"
")", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1066); AnnotateMozCrashReason("MOZ_ASSERT" "(" "srv == 0" ") ("
"SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER should be enabled" ")"
); do { *((volatile int*)__null) = 1066; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1066 "SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER should be enabled")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(srv == 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(srv == 0))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("srv == 0" " (" "SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER should be enabled"
")", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1066); AnnotateMozCrashReason("MOZ_ASSERT" "(" "srv == 0" ") ("
"SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER should be enabled" ")"
); do { *((volatile int*)__null) = 1066; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1067#endif
1068
1069 // Do not set mDatabaseFile or mFileURL here since this is a "memory"
1070 // database.
1071
1072 nsresult rv = initializeInternal();
1073 RecordOpenStatus(rv);
1074 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1074); return rv; } } while (false)
;
1075
1076 return NS_OK;
1077}
1078
1079nsresult Connection::initialize(nsIFile* aDatabaseFile) {
1080 NS_ASSERTION(aDatabaseFile, "Passed null file!")do { if (!(aDatabaseFile)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Passed null file!", "aDatabaseFile", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1080); MOZ_PretendNoReturn(); } } while (0)
;
1081 NS_ASSERTION(!connectionReady(),do { if (!(!connectionReady())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Initialize called on already opened database!", "!connectionReady()"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1082); MOZ_PretendNoReturn(); } } while (0)
1082 "Initialize called on already opened database!")do { if (!(!connectionReady())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Initialize called on already opened database!", "!connectionReady()"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1082); MOZ_PretendNoReturn(); } } while (0)
;
1083 AUTO_PROFILER_LABEL("Connection::initialize", OTHER)mozilla::AutoProfilerLabel raiiObject1083( "Connection::initialize"
, nullptr, JS::ProfilingCategoryPair::OTHER)
;
1084
1085 // Do not set mFileURL here since this is database does not have an associated
1086 // URL.
1087 mDatabaseFile = aDatabaseFile;
1088
1089 nsAutoString path;
1090 nsresult rv = aDatabaseFile->GetPath(path);
1091 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1091); return rv; } } while (false)
;
1092
1093 bool exclusive =
1094 StaticPrefs::storage_sqlite_exclusiveLock_enabled() && !mOpenNotExclusive;
1095 int srv;
1096 if (mIgnoreLockingMode) {
1097 exclusive = false;
1098 srv = ::sqlite3_open_v2(NS_ConvertUTF16toUTF8(path).get(), &mDBConn, mFlags,
1099 "readonly-immutable-nolock");
1100 } else {
1101 srv = ::sqlite3_open_v2(NS_ConvertUTF16toUTF8(path).get(), &mDBConn, mFlags,
1102 basevfs::GetVFSName(exclusive));
1103 if (exclusive && (srv == SQLITE_LOCKED6 || srv == SQLITE_BUSY5)) {
1104 // Retry without trying to get an exclusive lock.
1105 exclusive = false;
1106 srv = ::sqlite3_open_v2(NS_ConvertUTF16toUTF8(path).get(), &mDBConn,
1107 mFlags, basevfs::GetVFSName(false));
1108 }
1109 }
1110 if (srv != SQLITE_OK0) {
1111 mDBConn = nullptr;
1112 rv = convertResultCode(srv);
1113 RecordOpenStatus(rv);
1114 return rv;
1115 }
1116
1117 rv = initializeInternal();
1118 if (exclusive &&
1119 (rv == NS_ERROR_STORAGE_BUSY || rv == NS_ERROR_FILE_IS_LOCKED)) {
1120 // Usually SQLite will fail to acquire an exclusive lock on opening, but in
1121 // some cases it may successfully open the database and then lock on the
1122 // first query execution. When initializeInternal fails it closes the
1123 // connection, so we can try to restart it in non-exclusive mode.
1124 srv = ::sqlite3_open_v2(NS_ConvertUTF16toUTF8(path).get(), &mDBConn, mFlags,
1125 basevfs::GetVFSName(false));
1126 if (srv == SQLITE_OK0) {
1127 rv = initializeInternal();
1128 }
1129 }
1130
1131 RecordOpenStatus(rv);
1132 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1132); return rv; } } while (false)
;
1133
1134 return NS_OK;
1135}
1136
1137nsresult Connection::initialize(nsIFileURL* aFileURL) {
1138 NS_ASSERTION(aFileURL, "Passed null file URL!")do { if (!(aFileURL)) { NS_DebugBreak(NS_DEBUG_ASSERTION, "Passed null file URL!"
, "aFileURL", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1138); MOZ_PretendNoReturn(); } } while (0)
;
1139 NS_ASSERTION(!connectionReady(),do { if (!(!connectionReady())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Initialize called on already opened database!", "!connectionReady()"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1140); MOZ_PretendNoReturn(); } } while (0)
1140 "Initialize called on already opened database!")do { if (!(!connectionReady())) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Initialize called on already opened database!", "!connectionReady()"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1140); MOZ_PretendNoReturn(); } } while (0)
;
1141 AUTO_PROFILER_LABEL("Connection::initialize", OTHER)mozilla::AutoProfilerLabel raiiObject1141( "Connection::initialize"
, nullptr, JS::ProfilingCategoryPair::OTHER)
;
1142
1143 nsCOMPtr<nsIFile> databaseFile;
1144 nsresult rv = aFileURL->GetFile(getter_AddRefs(databaseFile));
1145 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1145); return rv; } } while (false)
;
1146
1147 // Set both mDatabaseFile and mFileURL here.
1148 mFileURL = aFileURL;
1149 mDatabaseFile = databaseFile;
1150
1151 nsAutoCString spec;
1152 rv = aFileURL->GetSpec(spec);
1153 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1153); return rv; } } while (false)
;
1154
1155 // If there is a key specified, we need to use the obfuscating VFS.
1156 nsAutoCString query;
1157 rv = aFileURL->GetQuery(query);
1158 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1158); return rv; } } while (false)
;
1159
1160 bool hasKey = false;
1161 bool hasDirectoryLockId = false;
1162
1163 MOZ_ALWAYS_TRUE(do { if ((__builtin_expect(!!(URLParams::Parse(query, true, [
&hasKey, &hasDirectoryLockId]( const nsACString& aName
, const nsACString& aValue) { if (aName.EqualsLiteral("key"
)) { hasKey = true; return true; } if (aName.EqualsLiteral("directoryLockId"
)) { hasDirectoryLockId = true; return true; } return true; }
)), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "URLParams::Parse(query, true, [&hasKey, &hasDirectoryLockId]( const nsACString& aName, const nsACString& aValue) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1176); AnnotateMozCrashReason("MOZ_CRASH(" "URLParams::Parse(query, true, [&hasKey, &hasDirectoryLockId]( const nsACString& aName, const nsACString& aValue) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
")"); do { *((volatile int*)__null) = 1176; __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1164 URLParams::Parse(query, true,do { if ((__builtin_expect(!!(URLParams::Parse(query, true, [
&hasKey, &hasDirectoryLockId]( const nsACString& aName
, const nsACString& aValue) { if (aName.EqualsLiteral("key"
)) { hasKey = true; return true; } if (aName.EqualsLiteral("directoryLockId"
)) { hasDirectoryLockId = true; return true; } return true; }
)), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "URLParams::Parse(query, true, [&hasKey, &hasDirectoryLockId]( const nsACString& aName, const nsACString& aValue) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1176); AnnotateMozCrashReason("MOZ_CRASH(" "URLParams::Parse(query, true, [&hasKey, &hasDirectoryLockId]( const nsACString& aName, const nsACString& aValue) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
")"); do { *((volatile int*)__null) = 1176; __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1165 [&hasKey, &hasDirectoryLockId](do { if ((__builtin_expect(!!(URLParams::Parse(query, true, [
&hasKey, &hasDirectoryLockId]( const nsACString& aName
, const nsACString& aValue) { if (aName.EqualsLiteral("key"
)) { hasKey = true; return true; } if (aName.EqualsLiteral("directoryLockId"
)) { hasDirectoryLockId = true; return true; } return true; }
)), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "URLParams::Parse(query, true, [&hasKey, &hasDirectoryLockId]( const nsACString& aName, const nsACString& aValue) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1176); AnnotateMozCrashReason("MOZ_CRASH(" "URLParams::Parse(query, true, [&hasKey, &hasDirectoryLockId]( const nsACString& aName, const nsACString& aValue) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
")"); do { *((volatile int*)__null) = 1176; __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1166 const nsACString& aName, const nsACString& aValue) {do { if ((__builtin_expect(!!(URLParams::Parse(query, true, [
&hasKey, &hasDirectoryLockId]( const nsACString& aName
, const nsACString& aValue) { if (aName.EqualsLiteral("key"
)) { hasKey = true; return true; } if (aName.EqualsLiteral("directoryLockId"
)) { hasDirectoryLockId = true; return true; } return true; }
)), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "URLParams::Parse(query, true, [&hasKey, &hasDirectoryLockId]( const nsACString& aName, const nsACString& aValue) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1176); AnnotateMozCrashReason("MOZ_CRASH(" "URLParams::Parse(query, true, [&hasKey, &hasDirectoryLockId]( const nsACString& aName, const nsACString& aValue) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
")"); do { *((volatile int*)__null) = 1176; __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1167 if (aName.EqualsLiteral("key")) {do { if ((__builtin_expect(!!(URLParams::Parse(query, true, [
&hasKey, &hasDirectoryLockId]( const nsACString& aName
, const nsACString& aValue) { if (aName.EqualsLiteral("key"
)) { hasKey = true; return true; } if (aName.EqualsLiteral("directoryLockId"
)) { hasDirectoryLockId = true; return true; } return true; }
)), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "URLParams::Parse(query, true, [&hasKey, &hasDirectoryLockId]( const nsACString& aName, const nsACString& aValue) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1176); AnnotateMozCrashReason("MOZ_CRASH(" "URLParams::Parse(query, true, [&hasKey, &hasDirectoryLockId]( const nsACString& aName, const nsACString& aValue) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
")"); do { *((volatile int*)__null) = 1176; __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1168 hasKey = true;do { if ((__builtin_expect(!!(URLParams::Parse(query, true, [
&hasKey, &hasDirectoryLockId]( const nsACString& aName
, const nsACString& aValue) { if (aName.EqualsLiteral("key"
)) { hasKey = true; return true; } if (aName.EqualsLiteral("directoryLockId"
)) { hasDirectoryLockId = true; return true; } return true; }
)), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "URLParams::Parse(query, true, [&hasKey, &hasDirectoryLockId]( const nsACString& aName, const nsACString& aValue) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1176); AnnotateMozCrashReason("MOZ_CRASH(" "URLParams::Parse(query, true, [&hasKey, &hasDirectoryLockId]( const nsACString& aName, const nsACString& aValue) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
")"); do { *((volatile int*)__null) = 1176; __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1169 return true;do { if ((__builtin_expect(!!(URLParams::Parse(query, true, [
&hasKey, &hasDirectoryLockId]( const nsACString& aName
, const nsACString& aValue) { if (aName.EqualsLiteral("key"
)) { hasKey = true; return true; } if (aName.EqualsLiteral("directoryLockId"
)) { hasDirectoryLockId = true; return true; } return true; }
)), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "URLParams::Parse(query, true, [&hasKey, &hasDirectoryLockId]( const nsACString& aName, const nsACString& aValue) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1176); AnnotateMozCrashReason("MOZ_CRASH(" "URLParams::Parse(query, true, [&hasKey, &hasDirectoryLockId]( const nsACString& aName, const nsACString& aValue) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
")"); do { *((volatile int*)__null) = 1176; __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1170 }do { if ((__builtin_expect(!!(URLParams::Parse(query, true, [
&hasKey, &hasDirectoryLockId]( const nsACString& aName
, const nsACString& aValue) { if (aName.EqualsLiteral("key"
)) { hasKey = true; return true; } if (aName.EqualsLiteral("directoryLockId"
)) { hasDirectoryLockId = true; return true; } return true; }
)), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "URLParams::Parse(query, true, [&hasKey, &hasDirectoryLockId]( const nsACString& aName, const nsACString& aValue) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1176); AnnotateMozCrashReason("MOZ_CRASH(" "URLParams::Parse(query, true, [&hasKey, &hasDirectoryLockId]( const nsACString& aName, const nsACString& aValue) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
")"); do { *((volatile int*)__null) = 1176; __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1171 if (aName.EqualsLiteral("directoryLockId")) {do { if ((__builtin_expect(!!(URLParams::Parse(query, true, [
&hasKey, &hasDirectoryLockId]( const nsACString& aName
, const nsACString& aValue) { if (aName.EqualsLiteral("key"
)) { hasKey = true; return true; } if (aName.EqualsLiteral("directoryLockId"
)) { hasDirectoryLockId = true; return true; } return true; }
)), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "URLParams::Parse(query, true, [&hasKey, &hasDirectoryLockId]( const nsACString& aName, const nsACString& aValue) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1176); AnnotateMozCrashReason("MOZ_CRASH(" "URLParams::Parse(query, true, [&hasKey, &hasDirectoryLockId]( const nsACString& aName, const nsACString& aValue) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
")"); do { *((volatile int*)__null) = 1176; __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1172 hasDirectoryLockId = true;do { if ((__builtin_expect(!!(URLParams::Parse(query, true, [
&hasKey, &hasDirectoryLockId]( const nsACString& aName
, const nsACString& aValue) { if (aName.EqualsLiteral("key"
)) { hasKey = true; return true; } if (aName.EqualsLiteral("directoryLockId"
)) { hasDirectoryLockId = true; return true; } return true; }
)), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "URLParams::Parse(query, true, [&hasKey, &hasDirectoryLockId]( const nsACString& aName, const nsACString& aValue) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1176); AnnotateMozCrashReason("MOZ_CRASH(" "URLParams::Parse(query, true, [&hasKey, &hasDirectoryLockId]( const nsACString& aName, const nsACString& aValue) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
")"); do { *((volatile int*)__null) = 1176; __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1173 return true;do { if ((__builtin_expect(!!(URLParams::Parse(query, true, [
&hasKey, &hasDirectoryLockId]( const nsACString& aName
, const nsACString& aValue) { if (aName.EqualsLiteral("key"
)) { hasKey = true; return true; } if (aName.EqualsLiteral("directoryLockId"
)) { hasDirectoryLockId = true; return true; } return true; }
)), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "URLParams::Parse(query, true, [&hasKey, &hasDirectoryLockId]( const nsACString& aName, const nsACString& aValue) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1176); AnnotateMozCrashReason("MOZ_CRASH(" "URLParams::Parse(query, true, [&hasKey, &hasDirectoryLockId]( const nsACString& aName, const nsACString& aValue) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
")"); do { *((volatile int*)__null) = 1176; __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1174 }do { if ((__builtin_expect(!!(URLParams::Parse(query, true, [
&hasKey, &hasDirectoryLockId]( const nsACString& aName
, const nsACString& aValue) { if (aName.EqualsLiteral("key"
)) { hasKey = true; return true; } if (aName.EqualsLiteral("directoryLockId"
)) { hasDirectoryLockId = true; return true; } return true; }
)), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "URLParams::Parse(query, true, [&hasKey, &hasDirectoryLockId]( const nsACString& aName, const nsACString& aValue) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1176); AnnotateMozCrashReason("MOZ_CRASH(" "URLParams::Parse(query, true, [&hasKey, &hasDirectoryLockId]( const nsACString& aName, const nsACString& aValue) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
")"); do { *((volatile int*)__null) = 1176; __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1175 return true;do { if ((__builtin_expect(!!(URLParams::Parse(query, true, [
&hasKey, &hasDirectoryLockId]( const nsACString& aName
, const nsACString& aValue) { if (aName.EqualsLiteral("key"
)) { hasKey = true; return true; } if (aName.EqualsLiteral("directoryLockId"
)) { hasDirectoryLockId = true; return true; } return true; }
)), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "URLParams::Parse(query, true, [&hasKey, &hasDirectoryLockId]( const nsACString& aName, const nsACString& aValue) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1176); AnnotateMozCrashReason("MOZ_CRASH(" "URLParams::Parse(query, true, [&hasKey, &hasDirectoryLockId]( const nsACString& aName, const nsACString& aValue) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
")"); do { *((volatile int*)__null) = 1176; __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1176 }))do { if ((__builtin_expect(!!(URLParams::Parse(query, true, [
&hasKey, &hasDirectoryLockId]( const nsACString& aName
, const nsACString& aValue) { if (aName.EqualsLiteral("key"
)) { hasKey = true; return true; } if (aName.EqualsLiteral("directoryLockId"
)) { hasDirectoryLockId = true; return true; } return true; }
)), 1))) { } else { do { do { } while (false); MOZ_ReportCrash
("" "URLParams::Parse(query, true, [&hasKey, &hasDirectoryLockId]( const nsACString& aName, const nsACString& aValue) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1176); AnnotateMozCrashReason("MOZ_CRASH(" "URLParams::Parse(query, true, [&hasKey, &hasDirectoryLockId]( const nsACString& aName, const nsACString& aValue) { if (aName.EqualsLiteral(\"key\")) { hasKey = true; return true; } if (aName.EqualsLiteral(\"directoryLockId\")) { hasDirectoryLockId = true; return true; } return true; })"
")"); do { *((volatile int*)__null) = 1176; __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
1177
1178 bool exclusive =
1179 StaticPrefs::storage_sqlite_exclusiveLock_enabled() && !mOpenNotExclusive;
1180
1181 const char* const vfs = hasKey ? obfsvfs::GetVFSName()
1182 : hasDirectoryLockId ? quotavfs::GetVFSName()
1183 : basevfs::GetVFSName(exclusive);
1184
1185 int srv = ::sqlite3_open_v2(spec.get(), &mDBConn, mFlags, vfs);
1186 if (srv != SQLITE_OK0) {
1187 mDBConn = nullptr;
1188 rv = convertResultCode(srv);
1189 RecordOpenStatus(rv);
1190 return rv;
1191 }
1192
1193 rv = initializeInternal();
1194 RecordOpenStatus(rv);
1195 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1195); return rv; } } while (false)
;
1196
1197 return NS_OK;
1198}
1199
1200nsresult Connection::initializeInternal() {
1201 MOZ_ASSERT(mDBConn)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mDBConn)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mDBConn))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mDBConn", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1201); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mDBConn" ")"
); do { *((volatile int*)__null) = 1201; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1202 auto guard = MakeScopeExit([&]() { initializeFailed(); });
1203
1204 mConnectionClosed = false;
1205
1206#ifdef MOZ_SQLITE_FTS3_TOKENIZER
1207 DebugOnly<int> srv2 =
1208 ::sqlite3_db_config(mDBConn, SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER1004, 1, 0);
1209 MOZ_ASSERT(srv2 == SQLITE_OK,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(srv2 == 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(srv2 == 0))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("srv2 == 0" " (" "SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER should be enabled"
")", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1210); AnnotateMozCrashReason("MOZ_ASSERT" "(" "srv2 == 0" ") ("
"SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER should be enabled" ")"
); do { *((volatile int*)__null) = 1210; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1210 "SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER should be enabled")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(srv2 == 0)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(srv2 == 0))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("srv2 == 0" " (" "SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER should be enabled"
")", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1210); AnnotateMozCrashReason("MOZ_ASSERT" "(" "srv2 == 0" ") ("
"SQLITE_DBCONFIG_ENABLE_FTS3_TOKENIZER should be enabled" ")"
); do { *((volatile int*)__null) = 1210; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1211#endif
1212
1213 // Properly wrap the database handle's mutex.
1214 sharedDBMutex.initWithMutex(sqlite3_db_mutex(mDBConn));
1215
1216 // SQLite tracing can slow down queries (especially long queries)
1217 // significantly. Don't trace unless the user is actively monitoring SQLite.
1218 if (MOZ_LOG_TEST(gStorageLog, LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(gStorageLog, LogLevel
::Debug)), 0))
) {
1219 ::sqlite3_trace_v2(mDBConn, SQLITE_TRACE_STMT0x01 | SQLITE_TRACE_PROFILE0x02,
1220 tracefunc, this);
1221
1222 MOZ_LOG(do { const ::mozilla::LogModule* moz_real_module = gStorageLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Opening connection to '%s' (%p)", mTelemetryFilename
.get(), this); } } while (0)
1223 gStorageLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gStorageLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Opening connection to '%s' (%p)", mTelemetryFilename
.get(), this); } } while (0)
1224 ("Opening connection to '%s' (%p)", mTelemetryFilename.get(), this))do { const ::mozilla::LogModule* moz_real_module = gStorageLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Opening connection to '%s' (%p)", mTelemetryFilename
.get(), this); } } while (0)
;
1225 }
1226
1227 int64_t pageSize = Service::kDefaultPageSize;
1228
1229 // Set page_size to the preferred default value. This is effective only if
1230 // the database has just been created, otherwise, if the database does not
1231 // use WAL journal mode, a VACUUM operation will updated its page_size.
1232 nsAutoCString pageSizeQuery(MOZ_STORAGE_UNIQUIFY_QUERY_STR"/* " "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
" */ "
1233 "PRAGMA page_size = ");
1234 pageSizeQuery.AppendInt(pageSize);
1235 int srv = executeSql(mDBConn, pageSizeQuery.get());
1236 if (srv != SQLITE_OK0) {
1237 return convertResultCode(srv);
1238 }
1239
1240 // Setting the cache_size forces the database open, verifying if it is valid
1241 // or corrupt. So this is executed regardless it being actually needed.
1242 // The cache_size is calculated from the actual page_size, to save memory.
1243 nsAutoCString cacheSizeQuery(MOZ_STORAGE_UNIQUIFY_QUERY_STR"/* " "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
" */ "
1244 "PRAGMA cache_size = ");
1245 cacheSizeQuery.AppendInt(-MAX_CACHE_SIZE_KIBIBYTES2048);
1246 srv = executeSql(mDBConn, cacheSizeQuery.get());
1247 if (srv != SQLITE_OK0) {
1248 return convertResultCode(srv);
1249 }
1250
1251 // Register our built-in SQL functions.
1252 srv = registerFunctions(mDBConn);
1253 if (srv != SQLITE_OK0) {
1254 return convertResultCode(srv);
1255 }
1256
1257 // Register our built-in SQL collating sequences.
1258 srv = registerCollations(mDBConn, mStorageService);
1259 if (srv != SQLITE_OK0) {
1260 return convertResultCode(srv);
1261 }
1262
1263 // Set the default synchronous value. Each consumer can switch this
1264 // accordingly to their needs.
1265#if defined(ANDROID)
1266 // Android prefers synchronous = OFF for performance reasons.
1267 Unused << ExecuteSimpleSQL("PRAGMA synchronous = OFF;"_ns);
1268#else
1269 // Normal is the suggested value for WAL journals.
1270 Unused << ExecuteSimpleSQL("PRAGMA synchronous = NORMAL;"_ns);
1271#endif
1272
1273 // Initialization succeeded, we can stop guarding for failures.
1274 guard.release();
1275 return NS_OK;
1276}
1277
1278nsresult Connection::initializeOnAsyncThread(nsIFile* aStorageFile) {
1279 MOZ_ASSERT(!IsOnCurrentSerialEventTarget(eventTargetOpenedOn))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!IsOnCurrentSerialEventTarget(eventTargetOpenedOn))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!IsOnCurrentSerialEventTarget(eventTargetOpenedOn)))
), 0))) { do { } while (false); MOZ_ReportAssertionFailure("!IsOnCurrentSerialEventTarget(eventTargetOpenedOn)"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1279); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsOnCurrentSerialEventTarget(eventTargetOpenedOn)"
")"); do { *((volatile int*)__null) = 1279; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1280 nsresult rv = aStorageFile
1281 ? initialize(aStorageFile)
1282 : initialize(kMozStorageMemoryStorageKey, VoidCString());
1283 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1284 // Shutdown the async thread, since initialization failed.
1285 MutexAutoLock lockedScope(sharedAsyncExecutionMutex);
1286 mAsyncExecutionThreadShuttingDown = true;
1287 nsCOMPtr<nsIRunnable> event =
1288 NewRunnableMethod("Connection::shutdownAsyncThread", this,
1289 &Connection::shutdownAsyncThread);
1290 Unused << NS_DispatchToMainThread(event);
1291 }
1292 return rv;
1293}
1294
1295void Connection::initializeFailed() {
1296 {
1297 MutexAutoLock lockedScope(sharedAsyncExecutionMutex);
1298 mConnectionClosed = true;
1299 }
1300 MOZ_ALWAYS_TRUE(::sqlite3_close(mDBConn) == SQLITE_OK)do { if ((__builtin_expect(!!(::sqlite3_close(mDBConn) == 0),
1))) { } else { do { do { } while (false); MOZ_ReportCrash(""
"::sqlite3_close(mDBConn) == SQLITE_OK", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1300); AnnotateMozCrashReason("MOZ_CRASH(" "::sqlite3_close(mDBConn) == SQLITE_OK"
")"); do { *((volatile int*)__null) = 1300; __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
1301 mDBConn = nullptr;
1302 sharedDBMutex.destroy();
1303}
1304
1305nsresult Connection::databaseElementExists(
1306 enum DatabaseElementType aElementType, const nsACString& aElementName,
1307 bool* _exists) {
1308 if (!connectionReady()) {
1309 return NS_ERROR_NOT_AVAILABLE;
1310 }
1311 nsresult rv = ensureOperationSupported(SYNCHRONOUS);
1312 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1313 return rv;
1314 }
1315
1316 // When constructing the query, make sure to SELECT the correct db's
1317 // sqlite_master if the user is prefixing the element with a specific db. ex:
1318 // sample.test
1319 nsCString query("SELECT name FROM (SELECT * FROM ");
1320 nsDependentCSubstring element;
1321 int32_t ind = aElementName.FindChar('.');
1322 if (ind == kNotFound) {
1323 element.Assign(aElementName);
1324 } else {
1325 nsDependentCSubstring db(Substring(aElementName, 0, ind + 1));
1326 element.Assign(Substring(aElementName, ind + 1, aElementName.Length()));
1327 query.Append(db);
1328 }
1329 query.AppendLiteral(
1330 "sqlite_master UNION ALL SELECT * FROM sqlite_temp_master) WHERE type = "
1331 "'");
1332
1333 switch (aElementType) {
1334 case INDEX:
1335 query.AppendLiteral("index");
1336 break;
1337 case TABLE:
1338 query.AppendLiteral("table");
1339 break;
1340 }
1341 query.AppendLiteral("' AND name ='");
1342 query.Append(element);
1343 query.Append('\'');
1344
1345 sqlite3_stmt* stmt;
1346 int srv = prepareStatement(mDBConn, query, &stmt);
1347 if (srv != SQLITE_OK0) {
1348 RecordQueryStatus(srv);
1349 return convertResultCode(srv);
1350 }
1351
1352 srv = stepStatement(mDBConn, stmt);
1353 // we just care about the return value from step
1354 (void)::sqlite3_finalize(stmt);
1355
1356 RecordQueryStatus(srv);
1357
1358 if (srv == SQLITE_ROW100) {
1359 *_exists = true;
1360 return NS_OK;
1361 }
1362 if (srv == SQLITE_DONE101) {
1363 *_exists = false;
1364 return NS_OK;
1365 }
1366
1367 return convertResultCode(srv);
1368}
1369
1370bool Connection::findFunctionByInstance(mozIStorageFunction* aInstance) {
1371 sharedDBMutex.assertCurrentThreadOwns();
1372
1373 for (const auto& data : mFunctions.Values()) {
1374 if (data.function == aInstance) {
1375 return true;
1376 }
1377 }
1378 return false;
1379}
1380
1381/* static */
1382int Connection::sProgressHelper(void* aArg) {
1383 Connection* _this = static_cast<Connection*>(aArg);
1384 return _this->progressHandler();
1385}
1386
1387int Connection::progressHandler() {
1388 sharedDBMutex.assertCurrentThreadOwns();
1389 if (mProgressHandler) {
1390 bool result;
1391 nsresult rv = mProgressHandler->OnProgress(this, &result);
1392 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) return 0; // Don't break request
1393 return result ? 1 : 0;
1394 }
1395 return 0;
1396}
1397
1398nsresult Connection::setClosedState() {
1399 // Flag that we are shutting down the async thread, so that
1400 // getAsyncExecutionTarget knows not to expose/create the async thread.
1401 MutexAutoLock lockedScope(sharedAsyncExecutionMutex);
1402 NS_ENSURE_FALSE(mAsyncExecutionThreadShuttingDown, NS_ERROR_UNEXPECTED)do { if ((__builtin_expect(!!(!(!(mAsyncExecutionThreadShuttingDown
))), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE("
"!(mAsyncExecutionThreadShuttingDown)" ") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1402); return NS_ERROR_UNEXPECTED; } } while (false)
;
1403
1404 mAsyncExecutionThreadShuttingDown = true;
1405
1406 // Set the property to null before closing the connection, otherwise the
1407 // other functions in the module may try to use the connection after it is
1408 // closed.
1409 mDBConn = nullptr;
1410
1411 return NS_OK;
1412}
1413
1414bool Connection::operationSupported(ConnectionOperation aOperationType) {
1415 if (aOperationType == ASYNCHRONOUS) {
1416 // Async operations are supported for all connections, on any thread.
1417 return true;
1418 }
1419 // Sync operations are supported for sync connections (on any thread), and
1420 // async connections on a background thread.
1421 MOZ_ASSERT(aOperationType == SYNCHRONOUS)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aOperationType == SYNCHRONOUS)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aOperationType == SYNCHRONOUS
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"aOperationType == SYNCHRONOUS", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1421); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aOperationType == SYNCHRONOUS"
")"); do { *((volatile int*)__null) = 1421; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1422 return mSupportedOperations == SYNCHRONOUS || !NS_IsMainThread();
1423}
1424
1425nsresult Connection::ensureOperationSupported(
1426 ConnectionOperation aOperationType) {
1427 if (NS_WARN_IF(!operationSupported(aOperationType))NS_warn_if_impl(!operationSupported(aOperationType), "!operationSupported(aOperationType)"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1427)
) {
1428#ifdef DEBUG1
1429 if (NS_IsMainThread()) {
1430 nsCOMPtr<nsIXPConnect> xpc = nsIXPConnect::XPConnect();
1431 Unused << xpc->DebugDumpJSStack(false, false, false);
1432 }
1433#endif
1434 MOZ_ASSERT(false,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "Don't use async connections synchronously on the main thread"
")", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1435); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"Don't use async connections synchronously on the main thread"
")"); do { *((volatile int*)__null) = 1435; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1435 "Don't use async connections synchronously on the main thread")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "Don't use async connections synchronously on the main thread"
")", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1435); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"Don't use async connections synchronously on the main thread"
")"); do { *((volatile int*)__null) = 1435; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1436 return NS_ERROR_NOT_AVAILABLE;
1437 }
1438 return NS_OK;
1439}
1440
1441bool Connection::isConnectionReadyOnThisThread() {
1442 MOZ_ASSERT_IF(connectionReady(), !mConnectionClosed)do { if (connectionReady()) { do { static_assert( mozilla::detail
::AssertionConditionType<decltype(!mConnectionClosed)>::
isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!mConnectionClosed))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!mConnectionClosed", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1442); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!mConnectionClosed"
")"); do { *((volatile int*)__null) = 1442; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
1443 if (mAsyncExecutionThread && mAsyncExecutionThread->IsOnCurrentThread()) {
1444 return true;
1445 }
1446 return connectionReady();
1447}
1448
1449bool Connection::isClosing() {
1450 MutexAutoLock lockedScope(sharedAsyncExecutionMutex);
1451 return mAsyncExecutionThreadShuttingDown && !mConnectionClosed;
1452}
1453
1454bool Connection::isClosed() {
1455 MutexAutoLock lockedScope(sharedAsyncExecutionMutex);
1456 return mConnectionClosed;
1457}
1458
1459bool Connection::isClosed(MutexAutoLock& lock) { return mConnectionClosed; }
1460
1461bool Connection::isAsyncExecutionThreadAvailable() {
1462 MOZ_ASSERT(IsOnCurrentSerialEventTarget(eventTargetOpenedOn))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsOnCurrentSerialEventTarget(eventTargetOpenedOn))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(IsOnCurrentSerialEventTarget(eventTargetOpenedOn))))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsOnCurrentSerialEventTarget(eventTargetOpenedOn)"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1462); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsOnCurrentSerialEventTarget(eventTargetOpenedOn)"
")"); do { *((volatile int*)__null) = 1462; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1463 return mAsyncExecutionThread && !mAsyncExecutionThreadShuttingDown;
1464}
1465
1466void Connection::shutdownAsyncThread() {
1467 MOZ_ASSERT(IsOnCurrentSerialEventTarget(eventTargetOpenedOn))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsOnCurrentSerialEventTarget(eventTargetOpenedOn))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(IsOnCurrentSerialEventTarget(eventTargetOpenedOn))))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsOnCurrentSerialEventTarget(eventTargetOpenedOn)"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1467); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsOnCurrentSerialEventTarget(eventTargetOpenedOn)"
")"); do { *((volatile int*)__null) = 1467; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1468 MOZ_ASSERT(mAsyncExecutionThread)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mAsyncExecutionThread)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mAsyncExecutionThread))), 0)
)) { do { } while (false); MOZ_ReportAssertionFailure("mAsyncExecutionThread"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1468); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mAsyncExecutionThread"
")"); do { *((volatile int*)__null) = 1468; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1469 MOZ_ASSERT(mAsyncExecutionThreadShuttingDown)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mAsyncExecutionThreadShuttingDown)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mAsyncExecutionThreadShuttingDown
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"mAsyncExecutionThreadShuttingDown", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1469); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mAsyncExecutionThreadShuttingDown"
")"); do { *((volatile int*)__null) = 1469; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1470
1471 MOZ_ALWAYS_SUCCEEDS(mAsyncExecutionThread->Shutdown())do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(mAsyncExecutionThread->Shutdown())), 1)))), 1))) { } else
{ do { do { } while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(mAsyncExecutionThread->Shutdown())"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1471); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(mAsyncExecutionThread->Shutdown())"
")"); do { *((volatile int*)__null) = 1471; __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
1472 mAsyncExecutionThread = nullptr;
1473}
1474
1475nsresult Connection::internalClose(sqlite3* aNativeConnection) {
1476#ifdef DEBUG1
1477 { // Make sure we have marked our async thread as shutting down.
1478 MutexAutoLock lockedScope(sharedAsyncExecutionMutex);
1479 MOZ_ASSERT(mAsyncExecutionThreadShuttingDown,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mAsyncExecutionThreadShuttingDown)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mAsyncExecutionThreadShuttingDown
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"mAsyncExecutionThreadShuttingDown" " (" "Did not call setClosedState!"
")", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1480); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mAsyncExecutionThreadShuttingDown"
") (" "Did not call setClosedState!" ")"); do { *((volatile int
*)__null) = 1480; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
1480 "Did not call setClosedState!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mAsyncExecutionThreadShuttingDown)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mAsyncExecutionThreadShuttingDown
))), 0))) { do { } while (false); MOZ_ReportAssertionFailure(
"mAsyncExecutionThreadShuttingDown" " (" "Did not call setClosedState!"
")", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1480); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mAsyncExecutionThreadShuttingDown"
") (" "Did not call setClosedState!" ")"); do { *((volatile int
*)__null) = 1480; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
1481 MOZ_ASSERT(!isClosed(lockedScope), "Unexpected closed state")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!isClosed(lockedScope))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!isClosed(lockedScope)))), 0
))) { do { } while (false); MOZ_ReportAssertionFailure("!isClosed(lockedScope)"
" (" "Unexpected closed state" ")", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1481); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!isClosed(lockedScope)"
") (" "Unexpected closed state" ")"); do { *((volatile int*)
__null) = 1481; __attribute__((nomerge)) ::abort(); } while (
false); } } while (false)
;
1482 }
1483#endif // DEBUG
1484
1485 if (MOZ_LOG_TEST(gStorageLog, LogLevel::Debug)(__builtin_expect(!!(mozilla::detail::log_test(gStorageLog, LogLevel
::Debug)), 0))
) {
1486 nsAutoCString leafName(":memory");
1487 if (mDatabaseFile) (void)mDatabaseFile->GetNativeLeafName(leafName);
1488 MOZ_LOG(gStorageLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gStorageLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Closing connection to '%s'", leafName.get
()); } } while (0)
1489 ("Closing connection to '%s'", leafName.get()))do { const ::mozilla::LogModule* moz_real_module = gStorageLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Closing connection to '%s'", leafName.get
()); } } while (0)
;
1490 }
1491
1492 // At this stage, we may still have statements that need to be
1493 // finalized. Attempt to close the database connection. This will
1494 // always disconnect any virtual tables and cleanly finalize their
1495 // internal statements. Once this is done, closing may fail due to
1496 // unfinalized client statements, in which case we need to finalize
1497 // these statements and close again.
1498 {
1499 MutexAutoLock lockedScope(sharedAsyncExecutionMutex);
1500 mConnectionClosed = true;
1501 }
1502
1503 // Nothing else needs to be done if we don't have a connection here.
1504 if (!aNativeConnection) return NS_OK;
1505
1506 int srv = ::sqlite3_close(aNativeConnection);
1507
1508 if (srv == SQLITE_BUSY5) {
1509 {
1510 // Nothing else should change the connection or statements status until we
1511 // are done here.
1512 SQLiteMutexAutoLock lockedScope(sharedDBMutex);
1513 // We still have non-finalized statements. Finalize them.
1514 sqlite3_stmt* stmt = nullptr;
1515 while ((stmt = ::sqlite3_next_stmt(aNativeConnection, stmt))) {
1516 MOZ_LOG(gStorageLog, LogLevel::Debug,do { const ::mozilla::LogModule* moz_real_module = gStorageLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Auto-finalizing SQL statement '%s' (%p)",
::sqlite3_sql(stmt), stmt); } } while (0)
1517 ("Auto-finalizing SQL statement '%s' (%p)", ::sqlite3_sql(stmt),do { const ::mozilla::LogModule* moz_real_module = gStorageLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Auto-finalizing SQL statement '%s' (%p)",
::sqlite3_sql(stmt), stmt); } } while (0)
1518 stmt))do { const ::mozilla::LogModule* moz_real_module = gStorageLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Debug)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Debug, "Auto-finalizing SQL statement '%s' (%p)",
::sqlite3_sql(stmt), stmt); } } while (0)
;
1519
1520#ifdef DEBUG1
1521 SmprintfPointer msg = ::mozilla::Smprintf(
1522 "SQL statement '%s' (%p) should have been finalized before closing "
1523 "the connection",
1524 ::sqlite3_sql(stmt), stmt);
1525 NS_WARNING(msg.get())NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1525)
;
1526#endif // DEBUG
1527
1528 srv = ::sqlite3_finalize(stmt);
1529
1530#ifdef DEBUG1
1531 if (srv != SQLITE_OK0) {
1532 SmprintfPointer msg = ::mozilla::Smprintf(
1533 "Could not finalize SQL statement (%p)", stmt);
1534 NS_WARNING(msg.get())NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1534)
;
1535 }
1536#endif // DEBUG
1537
1538 // Ensure that the loop continues properly, whether closing has
1539 // succeeded or not.
1540 if (srv == SQLITE_OK0) {
1541 stmt = nullptr;
1542 }
1543 }
1544 // Scope exiting will unlock the mutex before we invoke sqlite3_close()
1545 // again, since Sqlite will try to acquire it.
1546 }
1547
1548 // Now that all statements have been finalized, we
1549 // should be able to close.
1550 srv = ::sqlite3_close(aNativeConnection);
Value stored to 'srv' is never read
1551 MOZ_ASSERT(false,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "Had to forcibly close the database connection because not all "
"the statements have been finalized." ")", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1553); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"Had to forcibly close the database connection because not all "
"the statements have been finalized." ")"); do { *((volatile
int*)__null) = 1553; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
1552 "Had to forcibly close the database connection because not all "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "Had to forcibly close the database connection because not all "
"the statements have been finalized." ")", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1553); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"Had to forcibly close the database connection because not all "
"the statements have been finalized." ")"); do { *((volatile
int*)__null) = 1553; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
1553 "the statements have been finalized.")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "Had to forcibly close the database connection because not all "
"the statements have been finalized." ")", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1553); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"Had to forcibly close the database connection because not all "
"the statements have been finalized." ")"); do { *((volatile
int*)__null) = 1553; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
1554 }
1555
1556 if (srv == SQLITE_OK0) {
1557 sharedDBMutex.destroy();
1558 } else {
1559 MOZ_ASSERT(false,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "sqlite3_close failed. There are probably outstanding "
"statements that are listed above!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1561); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"sqlite3_close failed. There are probably outstanding " "statements that are listed above!"
")"); do { *((volatile int*)__null) = 1561; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1560 "sqlite3_close failed. There are probably outstanding "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "sqlite3_close failed. There are probably outstanding "
"statements that are listed above!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1561); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"sqlite3_close failed. There are probably outstanding " "statements that are listed above!"
")"); do { *((volatile int*)__null) = 1561; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
1561 "statements that are listed above!")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "sqlite3_close failed. There are probably outstanding "
"statements that are listed above!" ")", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1561); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"sqlite3_close failed. There are probably outstanding " "statements that are listed above!"
")"); do { *((volatile int*)__null) = 1561; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1562 }
1563
1564 return convertResultCode(srv);
1565}
1566
1567nsCString Connection::getFilename() { return mTelemetryFilename; }
1568
1569int Connection::stepStatement(sqlite3* aNativeConnection,
1570 sqlite3_stmt* aStatement) {
1571 MOZ_ASSERT(aStatement)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aStatement)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aStatement))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("aStatement", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1571); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aStatement"
")"); do { *((volatile int*)__null) = 1571; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1572
1573 AUTO_PROFILER_LABEL_DYNAMIC_CSTR("Connection::stepStatement", OTHER,mozilla::AutoProfilerLabel raiiObject1574( "Connection::stepStatement"
, ::sqlite3_sql(aStatement), JS::ProfilingCategoryPair::OTHER
)
1574 ::sqlite3_sql(aStatement))mozilla::AutoProfilerLabel raiiObject1574( "Connection::stepStatement"
, ::sqlite3_sql(aStatement), JS::ProfilingCategoryPair::OTHER
)
;
1575
1576 bool checkedMainThread = false;
1577 TimeStamp startTime = TimeStamp::Now();
1578
1579 // The connection may have been closed if the executing statement has been
1580 // created and cached after a call to asyncClose() but before the actual
1581 // sqlite3_close(). This usually happens when other tasks using cached
1582 // statements are asynchronously scheduled for execution and any of them ends
1583 // up after asyncClose. See bug 728653 for details.
1584 if (!isConnectionReadyOnThisThread()) return SQLITE_MISUSE21;
1585
1586 (void)::sqlite3_extended_result_codes(aNativeConnection, 1);
1587
1588 int srv;
1589 while ((srv = ::sqlite3_step(aStatement)) == SQLITE_LOCKED_SHAREDCACHE(6 | (1<<8))) {
1590 if (!checkedMainThread) {
1591 checkedMainThread = true;
1592 if (::NS_IsMainThread()) {
1593 NS_WARNING("We won't allow blocking on the main thread!")NS_DebugBreak(NS_DEBUG_WARNING, "We won't allow blocking on the main thread!"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1593)
;
1594 break;
1595 }
1596 }
1597
1598 srv = WaitForUnlockNotify(aNativeConnection);
1599 if (srv != SQLITE_OK0) {
1600 break;
1601 }
1602
1603 ::sqlite3_reset(aStatement);
1604 }
1605
1606 // Report very slow SQL statements to Telemetry
1607 TimeDuration duration = TimeStamp::Now() - startTime;
1608 const uint32_t threshold = NS_IsMainThread()
1609 ? Telemetry::kSlowSQLThresholdForMainThread
1610 : Telemetry::kSlowSQLThresholdForHelperThreads;
1611 if (duration.ToMilliseconds() >= threshold) {
1612 nsDependentCString statementString(::sqlite3_sql(aStatement));
1613 Telemetry::RecordSlowSQLStatement(
1614 statementString, mTelemetryFilename,
1615 static_cast<uint32_t>(duration.ToMilliseconds()));
1616 }
1617
1618 (void)::sqlite3_extended_result_codes(aNativeConnection, 0);
1619 // Drop off the extended result bits of the result code.
1620 return srv & 0xFF;
1621}
1622
1623int Connection::prepareStatement(sqlite3* aNativeConnection,
1624 const nsCString& aSQL, sqlite3_stmt** _stmt) {
1625 // We should not even try to prepare statements after the connection has
1626 // been closed.
1627 if (!isConnectionReadyOnThisThread()) return SQLITE_MISUSE21;
1628
1629 bool checkedMainThread = false;
1630
1631 (void)::sqlite3_extended_result_codes(aNativeConnection, 1);
1632
1633 int srv;
1634 while ((srv = ::sqlite3_prepare_v2(aNativeConnection, aSQL.get(), -1, _stmt,
1635 nullptr)) == SQLITE_LOCKED_SHAREDCACHE(6 | (1<<8))) {
1636 if (!checkedMainThread) {
1637 checkedMainThread = true;
1638 if (::NS_IsMainThread()) {
1639 NS_WARNING("We won't allow blocking on the main thread!")NS_DebugBreak(NS_DEBUG_WARNING, "We won't allow blocking on the main thread!"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1639)
;
1640 break;
1641 }
1642 }
1643
1644 srv = WaitForUnlockNotify(aNativeConnection);
1645 if (srv != SQLITE_OK0) {
1646 break;
1647 }
1648 }
1649
1650 if (srv != SQLITE_OK0) {
1651 nsCString warnMsg;
1652 warnMsg.AppendLiteral("The SQL statement '");
1653 warnMsg.Append(aSQL);
1654 warnMsg.AppendLiteral("' could not be compiled due to an error: ");
1655 warnMsg.Append(::sqlite3_errmsg(aNativeConnection));
1656
1657#ifdef DEBUG1
1658 NS_WARNING(warnMsg.get())NS_DebugBreak(NS_DEBUG_WARNING, warnMsg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1658)
;
1659#endif
1660 MOZ_LOG(gStorageLog, LogLevel::Error, ("%s", warnMsg.get()))do { const ::mozilla::LogModule* moz_real_module = gStorageLog
; if ((__builtin_expect(!!(mozilla::detail::log_test(moz_real_module
, LogLevel::Error)), 0))) { mozilla::detail::log_print(moz_real_module
, LogLevel::Error, "%s", warnMsg.get()); } } while (0)
;
1661 }
1662
1663 (void)::sqlite3_extended_result_codes(aNativeConnection, 0);
1664 // Drop off the extended result bits of the result code.
1665 int rc = srv & 0xFF;
1666 // sqlite will return OK on a comment only string and set _stmt to nullptr.
1667 // The callers of this function are used to only checking the return value,
1668 // so it is safer to return an error code.
1669 if (rc == SQLITE_OK0 && *_stmt == nullptr) {
1670 return SQLITE_MISUSE21;
1671 }
1672
1673 return rc;
1674}
1675
1676int Connection::executeSql(sqlite3* aNativeConnection, const char* aSqlString) {
1677 if (!isConnectionReadyOnThisThread()) return SQLITE_MISUSE21;
1678
1679 AUTO_PROFILER_LABEL_DYNAMIC_CSTR("Connection::executeSql", OTHER, aSqlString)mozilla::AutoProfilerLabel raiiObject1679( "Connection::executeSql"
, aSqlString, JS::ProfilingCategoryPair::OTHER)
;
1680
1681 TimeStamp startTime = TimeStamp::Now();
1682 int srv =
1683 ::sqlite3_exec(aNativeConnection, aSqlString, nullptr, nullptr, nullptr);
1684 RecordQueryStatus(srv);
1685
1686 // Report very slow SQL statements to Telemetry
1687 TimeDuration duration = TimeStamp::Now() - startTime;
1688 const uint32_t threshold = NS_IsMainThread()
1689 ? Telemetry::kSlowSQLThresholdForMainThread
1690 : Telemetry::kSlowSQLThresholdForHelperThreads;
1691 if (duration.ToMilliseconds() >= threshold) {
1692 nsDependentCString statementString(aSqlString);
1693 Telemetry::RecordSlowSQLStatement(
1694 statementString, mTelemetryFilename,
1695 static_cast<uint32_t>(duration.ToMilliseconds()));
1696 }
1697
1698 return srv;
1699}
1700
1701////////////////////////////////////////////////////////////////////////////////
1702//// nsIInterfaceRequestor
1703
1704NS_IMETHODIMPnsresult
1705Connection::GetInterface(const nsIID& aIID, void** _result) {
1706 if (aIID.Equals(NS_GET_IID(nsIEventTarget)(nsIEventTarget::COMTypeInfo<nsIEventTarget, void>::kIID
)
)) {
1707 nsIEventTarget* background = getAsyncExecutionTarget();
1708 NS_IF_ADDREF(background)ns_if_addref(background);
1709 *_result = background;
1710 return NS_OK;
1711 }
1712 return NS_ERROR_NO_INTERFACE;
1713}
1714
1715////////////////////////////////////////////////////////////////////////////////
1716//// mozIStorageConnection
1717
1718NS_IMETHODIMPnsresult
1719Connection::Close() {
1720 nsresult rv = ensureOperationSupported(SYNCHRONOUS);
1721 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1722 return rv;
1723 }
1724 return synchronousClose();
1725}
1726
1727nsresult Connection::synchronousClose() {
1728 if (!connectionReady()) {
1729 return NS_ERROR_NOT_INITIALIZED;
1730 }
1731
1732#ifdef DEBUG1
1733 // Since we're accessing mAsyncExecutionThread, we need to be on the opener
1734 // event target. We make this check outside of debug code below in
1735 // setClosedState, but this is here to be explicit.
1736 MOZ_ASSERT(IsOnCurrentSerialEventTarget(eventTargetOpenedOn))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsOnCurrentSerialEventTarget(eventTargetOpenedOn))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(IsOnCurrentSerialEventTarget(eventTargetOpenedOn))))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsOnCurrentSerialEventTarget(eventTargetOpenedOn)"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1736); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsOnCurrentSerialEventTarget(eventTargetOpenedOn)"
")"); do { *((volatile int*)__null) = 1736; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1737#endif // DEBUG
1738
1739 // Make sure we have not executed any asynchronous statements.
1740 // If this fails, the mDBConn may be left open, resulting in a leak.
1741 // We'll try to finalize the pending statements and close the connection.
1742 if (isAsyncExecutionThreadAvailable()) {
1743#ifdef DEBUG1
1744 if (NS_IsMainThread()) {
1745 nsCOMPtr<nsIXPConnect> xpc = nsIXPConnect::XPConnect();
1746 Unused << xpc->DebugDumpJSStack(false, false, false);
1747 }
1748#endif
1749 MOZ_ASSERT(false,do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "Close() was invoked on a connection that executed asynchronous "
"statements. " "Should have used asyncClose()." ")", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1752); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"Close() was invoked on a connection that executed asynchronous "
"statements. " "Should have used asyncClose()." ")"); do { *
((volatile int*)__null) = 1752; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
1750 "Close() was invoked on a connection that executed asynchronous "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "Close() was invoked on a connection that executed asynchronous "
"statements. " "Should have used asyncClose()." ")", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1752); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"Close() was invoked on a connection that executed asynchronous "
"statements. " "Should have used asyncClose()." ")"); do { *
((volatile int*)__null) = 1752; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
1751 "statements. "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "Close() was invoked on a connection that executed asynchronous "
"statements. " "Should have used asyncClose()." ")", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1752); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"Close() was invoked on a connection that executed asynchronous "
"statements. " "Should have used asyncClose()." ")"); do { *
((volatile int*)__null) = 1752; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
1752 "Should have used asyncClose().")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "Close() was invoked on a connection that executed asynchronous "
"statements. " "Should have used asyncClose()." ")", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1752); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"Close() was invoked on a connection that executed asynchronous "
"statements. " "Should have used asyncClose()." ")"); do { *
((volatile int*)__null) = 1752; __attribute__((nomerge)) ::abort
(); } while (false); } } while (false)
;
1753 // Try to close the database regardless, to free up resources.
1754 Unused << SpinningSynchronousClose();
1755 return NS_ERROR_UNEXPECTED;
1756 }
1757
1758 // setClosedState nullifies our connection pointer, so we take a raw pointer
1759 // off it, to pass it through the close procedure.
1760 sqlite3* nativeConn = mDBConn;
1761 nsresult rv = setClosedState();
1762 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1762); return rv; } } while (false)
;
1763
1764 return internalClose(nativeConn);
1765}
1766
1767NS_IMETHODIMPnsresult
1768Connection::SpinningSynchronousClose() {
1769 nsresult rv = ensureOperationSupported(SYNCHRONOUS);
1770 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1771 return rv;
1772 }
1773 if (!IsOnCurrentSerialEventTarget(eventTargetOpenedOn)) {
1774 return NS_ERROR_NOT_SAME_THREAD;
1775 }
1776
1777 // As currently implemented, we can't spin to wait for an existing AsyncClose.
1778 // Our only existing caller will never have called close; assert if misused
1779 // so that no new callers assume this works after an AsyncClose.
1780 MOZ_DIAGNOSTIC_ASSERT(connectionReady())do { static_assert( mozilla::detail::AssertionConditionType<
decltype(connectionReady())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(connectionReady()))), 0))) {
do { } while (false); MOZ_ReportAssertionFailure("connectionReady()"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1780); AnnotateMozCrashReason("MOZ_DIAGNOSTIC_ASSERT" "(" "connectionReady()"
")"); do { *((volatile int*)__null) = 1780; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1781 if (!connectionReady()) {
1782 return NS_ERROR_UNEXPECTED;
1783 }
1784
1785 RefPtr<CloseListener> listener = new CloseListener();
1786 rv = AsyncClose(listener);
1787 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1787); return rv; } } while (false)
;
1788 MOZ_ALWAYS_TRUE(do { if ((__builtin_expect(!!(SpinEventLoopUntil("storage::Connection::SpinningSynchronousClose"_ns
, [&]() { return listener->mClosed; })), 1))) { } else
{ do { do { } while (false); MOZ_ReportCrash("" "SpinEventLoopUntil(\"storage::Connection::SpinningSynchronousClose\"_ns, [&]() { return listener->mClosed; })"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1790); AnnotateMozCrashReason("MOZ_CRASH(" "SpinEventLoopUntil(\"storage::Connection::SpinningSynchronousClose\"_ns, [&]() { return listener->mClosed; })"
")"); do { *((volatile int*)__null) = 1790; __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1789 SpinEventLoopUntil("storage::Connection::SpinningSynchronousClose"_ns,do { if ((__builtin_expect(!!(SpinEventLoopUntil("storage::Connection::SpinningSynchronousClose"_ns
, [&]() { return listener->mClosed; })), 1))) { } else
{ do { do { } while (false); MOZ_ReportCrash("" "SpinEventLoopUntil(\"storage::Connection::SpinningSynchronousClose\"_ns, [&]() { return listener->mClosed; })"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1790); AnnotateMozCrashReason("MOZ_CRASH(" "SpinEventLoopUntil(\"storage::Connection::SpinningSynchronousClose\"_ns, [&]() { return listener->mClosed; })"
")"); do { *((volatile int*)__null) = 1790; __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
1790 [&]() { return listener->mClosed; }))do { if ((__builtin_expect(!!(SpinEventLoopUntil("storage::Connection::SpinningSynchronousClose"_ns
, [&]() { return listener->mClosed; })), 1))) { } else
{ do { do { } while (false); MOZ_ReportCrash("" "SpinEventLoopUntil(\"storage::Connection::SpinningSynchronousClose\"_ns, [&]() { return listener->mClosed; })"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1790); AnnotateMozCrashReason("MOZ_CRASH(" "SpinEventLoopUntil(\"storage::Connection::SpinningSynchronousClose\"_ns, [&]() { return listener->mClosed; })"
")"); do { *((volatile int*)__null) = 1790; __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
1791 MOZ_ASSERT(isClosed(), "The connection should be closed at this point")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(isClosed())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(isClosed()))), 0))) { do { }
while (false); MOZ_ReportAssertionFailure("isClosed()" " (" "The connection should be closed at this point"
")", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1791); AnnotateMozCrashReason("MOZ_ASSERT" "(" "isClosed()"
") (" "The connection should be closed at this point" ")"); do
{ *((volatile int*)__null) = 1791; __attribute__((nomerge)) ::
abort(); } while (false); } } while (false)
;
1792
1793 return rv;
1794}
1795
1796NS_IMETHODIMPnsresult
1797Connection::AsyncClose(mozIStorageCompletionCallback* aCallback) {
1798 NS_ENSURE_TRUE(NS_IsMainThread(), NS_ERROR_NOT_SAME_THREAD)do { if ((__builtin_expect(!!(!(NS_IsMainThread())), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "NS_IsMainThread()" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1798); return NS_ERROR_NOT_SAME_THREAD; } } while (false)
;
1799 // Check if AsyncClose or Close were already invoked.
1800 if (!connectionReady()) {
1801 return NS_ERROR_NOT_INITIALIZED;
1802 }
1803 nsresult rv = ensureOperationSupported(ASYNCHRONOUS);
1804 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1805 return rv;
1806 }
1807
1808 // The two relevant factors at this point are whether we have a database
1809 // connection and whether we have an async execution thread. Here's what the
1810 // states mean and how we handle them:
1811 //
1812 // - (mDBConn && asyncThread): The expected case where we are either an
1813 // async connection or a sync connection that has been used asynchronously.
1814 // Either way the caller must call us and not Close(). Nothing surprising
1815 // about this. We'll dispatch AsyncCloseConnection to the already-existing
1816 // async thread.
1817 //
1818 // - (mDBConn && !asyncThread): A somewhat unusual case where the caller
1819 // opened the connection synchronously and was planning to use it
1820 // asynchronously, but never got around to using it asynchronously before
1821 // needing to shutdown. This has been observed to happen for the cookie
1822 // service in a case where Firefox shuts itself down almost immediately
1823 // after startup (for unknown reasons). In the Firefox shutdown case,
1824 // we may also fail to create a new async execution thread if one does not
1825 // already exist. (nsThreadManager will refuse to create new threads when
1826 // it has already been told to shutdown.) As such, we need to handle a
1827 // failure to create the async execution thread by falling back to
1828 // synchronous Close() and also dispatching the completion callback because
1829 // at least Places likes to spin a nested event loop that depends on the
1830 // callback being invoked.
1831 //
1832 // Note that we have considered not trying to spin up the async execution
1833 // thread in this case if it does not already exist, but the overhead of
1834 // thread startup (if successful) is significantly less expensive than the
1835 // worst-case potential I/O hit of synchronously closing a database when we
1836 // could close it asynchronously.
1837 //
1838 // - (!mDBConn && asyncThread): This happens in some but not all cases where
1839 // OpenAsyncDatabase encountered a problem opening the database. If it
1840 // happened in all cases AsyncInitDatabase would just shut down the thread
1841 // directly and we would avoid this case. But it doesn't, so for simplicity
1842 // and consistency AsyncCloseConnection knows how to handle this and we
1843 // act like this was the (mDBConn && asyncThread) case in this method.
1844 //
1845 // - (!mDBConn && !asyncThread): The database was never successfully opened or
1846 // Close() or AsyncClose() has already been called (at least) once. This is
1847 // undeniably a misuse case by the caller. We could optimize for this
1848 // case by adding an additional check of mAsyncExecutionThread without using
1849 // getAsyncExecutionTarget() to avoid wastefully creating a thread just to
1850 // shut it down. But this complicates the method for broken caller code
1851 // whereas we're still correct and safe without the special-case.
1852 nsIEventTarget* asyncThread = getAsyncExecutionTarget();
1853
1854 // Create our callback event if we were given a callback. This will
1855 // eventually be dispatched in all cases, even if we fall back to Close() and
1856 // the database wasn't open and we return an error. The rationale is that
1857 // no existing consumer checks our return value and several of them like to
1858 // spin nested event loops until the callback fires. Given that, it seems
1859 // preferable for us to dispatch the callback in all cases. (Except the
1860 // wrong thread misuse case we bailed on up above. But that's okay because
1861 // that is statically wrong whereas these edge cases are dynamic.)
1862 nsCOMPtr<nsIRunnable> completeEvent;
1863 if (aCallback) {
1864 completeEvent = newCompletionEvent(aCallback);
1865 }
1866
1867 if (!asyncThread) {
1868 // We were unable to create an async thread, so we need to fall back to
1869 // using normal Close(). Since there is no async thread, Close() will
1870 // not complain about that. (Close() may, however, complain if the
1871 // connection is closed, but that's okay.)
1872 if (completeEvent) {
1873 // Closing the database is more important than returning an error code
1874 // about a failure to dispatch, especially because all existing native
1875 // callers ignore our return value.
1876 Unused << NS_DispatchToMainThread(completeEvent.forget());
1877 }
1878 MOZ_ALWAYS_SUCCEEDS(synchronousClose())do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(synchronousClose())), 1)))), 1))) { } else { do { do { } while
(false); MOZ_ReportCrash("" "NS_SUCCEEDED(synchronousClose())"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1878); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(synchronousClose())"
")"); do { *((volatile int*)__null) = 1878; __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
1879 // Return a success inconditionally here, since Close() is unlikely to fail
1880 // and we want to reassure the consumer that its callback will be invoked.
1881 return NS_OK;
1882 }
1883
1884 // If we're closing the connection during shutdown, and there is an
1885 // interruptible statement running on the helper thread, issue a
1886 // sqlite3_interrupt() to avoid crashing when that statement takes a long
1887 // time (for example a vacuum).
1888 if (AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownConfirmed) &&
1889 mInterruptible && mIsStatementOnHelperThreadInterruptible) {
1890 MOZ_ASSERT(!isClosing(), "Must not be closing, see Interrupt()")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!isClosing())>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!isClosing()))), 0))) { do {
} while (false); MOZ_ReportAssertionFailure("!isClosing()" " ("
"Must not be closing, see Interrupt()" ")", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1890); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!isClosing()"
") (" "Must not be closing, see Interrupt()" ")"); do { *((volatile
int*)__null) = 1890; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
1891 DebugOnly<nsresult> rv2 = Interrupt();
1892 MOZ_ASSERT(NS_SUCCEEDED(rv2))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv2)), 1
))))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv2)), 1
)))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv2)), 1)))", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1892); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv2)), 1)))"
")"); do { *((volatile int*)__null) = 1892; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
1893 }
1894
1895 // setClosedState nullifies our connection pointer, so we take a raw pointer
1896 // off it, to pass it through the close procedure.
1897 sqlite3* nativeConn = mDBConn;
1898 rv = setClosedState();
1899 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1899); return rv; } } while (false)
;
1900
1901 // Create and dispatch our close event to the background thread.
1902 nsCOMPtr<nsIRunnable> closeEvent =
1903 new AsyncCloseConnection(this, nativeConn, completeEvent);
1904 rv = asyncThread->Dispatch(closeEvent, NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL);
1905 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1905); return rv; } } while (false)
;
1906
1907 return NS_OK;
1908}
1909
1910NS_IMETHODIMPnsresult
1911Connection::AsyncClone(bool aReadOnly,
1912 mozIStorageCompletionCallback* aCallback) {
1913 AUTO_PROFILER_LABEL("Connection::AsyncClone", OTHER)mozilla::AutoProfilerLabel raiiObject1913( "Connection::AsyncClone"
, nullptr, JS::ProfilingCategoryPair::OTHER)
;
1914
1915 NS_ENSURE_TRUE(NS_IsMainThread(), NS_ERROR_NOT_SAME_THREAD)do { if ((__builtin_expect(!!(!(NS_IsMainThread())), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "NS_IsMainThread()" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1915); return NS_ERROR_NOT_SAME_THREAD; } } while (false)
;
1916 if (!connectionReady()) {
1917 return NS_ERROR_NOT_INITIALIZED;
1918 }
1919 nsresult rv = ensureOperationSupported(ASYNCHRONOUS);
1920 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1921 return rv;
1922 }
1923 if (!mDatabaseFile) return NS_ERROR_UNEXPECTED;
1924
1925 int flags = mFlags;
1926 if (aReadOnly) {
1927 // Turn off SQLITE_OPEN_READWRITE, and set SQLITE_OPEN_READONLY.
1928 flags = (~SQLITE_OPEN_READWRITE0x00000002 & flags) | SQLITE_OPEN_READONLY0x00000001;
1929 // Turn off SQLITE_OPEN_CREATE.
1930 flags = (~SQLITE_OPEN_CREATE0x00000004 & flags);
1931 }
1932
1933 // The cloned connection will still implement the synchronous API, but throw
1934 // if any synchronous methods are called on the main thread.
1935 RefPtr<Connection> clone =
1936 new Connection(mStorageService, flags, ASYNCHRONOUS, mTelemetryFilename,
1937 mInterruptible, mIgnoreLockingMode, mOpenNotExclusive);
1938
1939 RefPtr<AsyncInitializeClone> initEvent =
1940 new AsyncInitializeClone(this, clone, aReadOnly, aCallback);
1941 // Dispatch to our async thread, since the originating connection must remain
1942 // valid and open for the whole cloning process. This also ensures we are
1943 // properly serialized with a `close` operation, rather than race with it.
1944 nsCOMPtr<nsIEventTarget> target = getAsyncExecutionTarget();
1945 if (!target) {
1946 return NS_ERROR_UNEXPECTED;
1947 }
1948 return target->Dispatch(initEvent, NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL);
1949}
1950
1951nsresult Connection::initializeClone(Connection* aClone, bool aReadOnly) {
1952 nsresult rv;
1953 if (!mStorageKey.IsEmpty()) {
1954 rv = aClone->initialize(mStorageKey, mName);
1955 } else if (mFileURL) {
1956 rv = aClone->initialize(mFileURL);
1957 } else {
1958 rv = aClone->initialize(mDatabaseFile);
1959 }
1960 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
1961 return rv;
1962 }
1963
1964 auto guard = MakeScopeExit([&]() { aClone->initializeFailed(); });
1965
1966 rv = aClone->SetDefaultTransactionType(mDefaultTransactionType);
1967 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1967); return rv; } } while (false)
;
1968
1969 // Re-attach on-disk databases that were attached to the original connection.
1970 {
1971 nsCOMPtr<mozIStorageStatement> stmt;
1972 rv = CreateStatement("PRAGMA database_list"_ns, getter_AddRefs(stmt));
1973 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1973); return rv; } } while (false)
;
1974 bool hasResult = false;
1975 while (stmt && NS_SUCCEEDED(stmt->ExecuteStep(&hasResult))((bool)(__builtin_expect(!!(!NS_FAILED_impl(stmt->ExecuteStep
(&hasResult))), 1)))
&& hasResult) {
1976 nsAutoCString name;
1977 rv = stmt->GetUTF8String(1, name);
1978 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !name.EqualsLiteral("main") &&
1979 !name.EqualsLiteral("temp")) {
1980 nsCString path;
1981 rv = stmt->GetUTF8String(2, path);
1982 if (NS_SUCCEEDED(rv)((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1))) && !path.IsEmpty()) {
1983 nsCOMPtr<mozIStorageStatement> attachStmt;
1984 rv = aClone->CreateStatement("ATTACH DATABASE :path AS "_ns + name,
1985 getter_AddRefs(attachStmt));
1986 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1986); return rv; } } while (false)
;
1987 rv = attachStmt->BindUTF8StringByName("path"_ns, path);
1988 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1988); return rv; } } while (false)
;
1989 rv = attachStmt->Execute();
1990 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 1990); return rv; } } while (false)
;
1991 }
1992 }
1993 }
1994 }
1995
1996 // Copy over pragmas from the original connection.
1997 // LIMITATION WARNING! Many of these pragmas are actually scoped to the
1998 // schema ("main" and any other attached databases), and this implmentation
1999 // fails to propagate them. This is being addressed on trunk.
2000 static const char* pragmas[] = {
2001 "cache_size", "temp_store", "foreign_keys", "journal_size_limit",
2002 "synchronous", "wal_autocheckpoint", "busy_timeout"};
2003 for (auto& pragma : pragmas) {
2004 // Read-only connections just need cache_size and temp_store pragmas.
2005 if (aReadOnly && ::strcmp(pragma, "cache_size") != 0 &&
2006 ::strcmp(pragma, "temp_store") != 0) {
2007 continue;
2008 }
2009
2010 nsAutoCString pragmaQuery("PRAGMA ");
2011 pragmaQuery.Append(pragma);
2012 nsCOMPtr<mozIStorageStatement> stmt;
2013 rv = CreateStatement(pragmaQuery, getter_AddRefs(stmt));
2014 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2014); return rv; } } while (false)
;
2015 bool hasResult = false;
2016 if (stmt && NS_SUCCEEDED(stmt->ExecuteStep(&hasResult))((bool)(__builtin_expect(!!(!NS_FAILED_impl(stmt->ExecuteStep
(&hasResult))), 1)))
&& hasResult) {
2017 pragmaQuery.AppendLiteral(" = ");
2018 pragmaQuery.AppendInt(stmt->AsInt32(0));
2019 rv = aClone->ExecuteSimpleSQL(pragmaQuery);
2020 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2020); return rv; } } while (false)
;
2021 }
2022 }
2023
2024 // Copy over temporary tables, triggers, and views from the original
2025 // connections. Entities in `sqlite_temp_master` are only visible to the
2026 // connection that created them.
2027 if (!aReadOnly) {
2028 rv = aClone->ExecuteSimpleSQL("BEGIN TRANSACTION"_ns);
2029 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2029); return rv; } } while (false)
;
2030
2031 nsCOMPtr<mozIStorageStatement> stmt;
2032 rv = CreateStatement(nsLiteralCString("SELECT sql FROM sqlite_temp_master "
2033 "WHERE type IN ('table', 'view', "
2034 "'index', 'trigger')"),
2035 getter_AddRefs(stmt));
2036 // Propagate errors, because failing to copy triggers might cause schema
2037 // coherency issues when writing to the database from the cloned connection.
2038 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2038); return rv; } } while (false)
;
2039 bool hasResult = false;
2040 while (stmt && NS_SUCCEEDED(stmt->ExecuteStep(&hasResult))((bool)(__builtin_expect(!!(!NS_FAILED_impl(stmt->ExecuteStep
(&hasResult))), 1)))
&& hasResult) {
2041 nsAutoCString query;
2042 rv = stmt->GetUTF8String(0, query);
2043 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2043); return rv; } } while (false)
;
2044
2045 // The `CREATE` SQL statements in `sqlite_temp_master` omit the `TEMP`
2046 // keyword. We need to add it back, or we'll recreate temporary entities
2047 // as persistent ones. `sqlite_temp_master` also holds `CREATE INDEX`
2048 // statements, but those don't need `TEMP` keywords.
2049 if (StringBeginsWith(query, "CREATE TABLE "_ns) ||
2050 StringBeginsWith(query, "CREATE TRIGGER "_ns) ||
2051 StringBeginsWith(query, "CREATE VIEW "_ns)) {
2052 query.Replace(0, 6, "CREATE TEMP");
2053 }
2054
2055 rv = aClone->ExecuteSimpleSQL(query);
2056 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2056); return rv; } } while (false)
;
2057 }
2058
2059 rv = aClone->ExecuteSimpleSQL("COMMIT"_ns);
2060 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2060); return rv; } } while (false)
;
2061 }
2062
2063 // Copy any functions that have been added to this connection.
2064 SQLiteMutexAutoLock lockedScope(sharedDBMutex);
2065 for (const auto& entry : mFunctions) {
2066 const nsACString& key = entry.GetKey();
2067 Connection::FunctionInfo data = entry.GetData();
2068
2069 rv = aClone->CreateFunction(key, data.numArgs, data.function);
2070 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2071 NS_WARNING("Failed to copy function to cloned connection")NS_DebugBreak(NS_DEBUG_WARNING, "Failed to copy function to cloned connection"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2071)
;
2072 }
2073 }
2074
2075 // Load SQLite extensions that were on this connection.
2076 // Copy into an array rather than holding the mutex while we load extensions.
2077 nsTArray<nsCString> loadedExtensions;
2078 {
2079 MutexAutoLock lockedScope(sharedAsyncExecutionMutex);
2080 AppendToArray(loadedExtensions, mLoadedExtensions);
2081 }
2082 for (const auto& extension : loadedExtensions) {
2083 (void)aClone->LoadExtension(extension, nullptr);
2084 }
2085
2086 guard.release();
2087 return NS_OK;
2088}
2089
2090NS_IMETHODIMPnsresult
2091Connection::Clone(bool aReadOnly, mozIStorageConnection** _connection) {
2092 MOZ_ASSERT(IsOnCurrentSerialEventTarget(eventTargetOpenedOn))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsOnCurrentSerialEventTarget(eventTargetOpenedOn))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(IsOnCurrentSerialEventTarget(eventTargetOpenedOn))))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsOnCurrentSerialEventTarget(eventTargetOpenedOn)"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2092); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsOnCurrentSerialEventTarget(eventTargetOpenedOn)"
")"); do { *((volatile int*)__null) = 2092; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2093
2094 AUTO_PROFILER_LABEL("Connection::Clone", OTHER)mozilla::AutoProfilerLabel raiiObject2094( "Connection::Clone"
, nullptr, JS::ProfilingCategoryPair::OTHER)
;
2095
2096 if (!connectionReady()) {
2097 return NS_ERROR_NOT_INITIALIZED;
2098 }
2099 nsresult rv = ensureOperationSupported(SYNCHRONOUS);
2100 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2101 return rv;
2102 }
2103
2104 int flags = mFlags;
2105 if (aReadOnly) {
2106 // Turn off SQLITE_OPEN_READWRITE, and set SQLITE_OPEN_READONLY.
2107 flags = (~SQLITE_OPEN_READWRITE0x00000002 & flags) | SQLITE_OPEN_READONLY0x00000001;
2108 // Turn off SQLITE_OPEN_CREATE.
2109 flags = (~SQLITE_OPEN_CREATE0x00000004 & flags);
2110 }
2111
2112 RefPtr<Connection> clone =
2113 new Connection(mStorageService, flags, mSupportedOperations,
2114 mTelemetryFilename, mInterruptible);
2115
2116 rv = initializeClone(clone, aReadOnly);
2117 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2118 return rv;
2119 }
2120
2121 NS_IF_ADDREF(*_connection = clone)ns_if_addref(*_connection = clone);
2122 return NS_OK;
2123}
2124
2125NS_IMETHODIMPnsresult
2126Connection::Interrupt() {
2127 MOZ_ASSERT(mInterruptible, "Interrupt method not allowed")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mInterruptible)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mInterruptible))), 0))) { do
{ } while (false); MOZ_ReportAssertionFailure("mInterruptible"
" (" "Interrupt method not allowed" ")", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2127); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mInterruptible"
") (" "Interrupt method not allowed" ")"); do { *((volatile int
*)__null) = 2127; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
2128 MOZ_ASSERT_IF(SYNCHRONOUS == mSupportedOperations,do { if (SYNCHRONOUS == mSupportedOperations) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(!IsOnCurrentSerialEventTarget
(eventTargetOpenedOn))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!IsOnCurrentSerialEventTarget
(eventTargetOpenedOn)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!IsOnCurrentSerialEventTarget(eventTargetOpenedOn)", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2129); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsOnCurrentSerialEventTarget(eventTargetOpenedOn)"
")"); do { *((volatile int*)__null) = 2129; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
2129 !IsOnCurrentSerialEventTarget(eventTargetOpenedOn))do { if (SYNCHRONOUS == mSupportedOperations) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(!IsOnCurrentSerialEventTarget
(eventTargetOpenedOn))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(!IsOnCurrentSerialEventTarget
(eventTargetOpenedOn)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!IsOnCurrentSerialEventTarget(eventTargetOpenedOn)", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2129); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!IsOnCurrentSerialEventTarget(eventTargetOpenedOn)"
")"); do { *((volatile int*)__null) = 2129; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
2130 MOZ_ASSERT_IF(ASYNCHRONOUS == mSupportedOperations,do { if (ASYNCHRONOUS == mSupportedOperations) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(IsOnCurrentSerialEventTarget
(eventTargetOpenedOn))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsOnCurrentSerialEventTarget
(eventTargetOpenedOn)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("IsOnCurrentSerialEventTarget(eventTargetOpenedOn)", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2131); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsOnCurrentSerialEventTarget(eventTargetOpenedOn)"
")"); do { *((volatile int*)__null) = 2131; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
2131 IsOnCurrentSerialEventTarget(eventTargetOpenedOn))do { if (ASYNCHRONOUS == mSupportedOperations) { do { static_assert
( mozilla::detail::AssertionConditionType<decltype(IsOnCurrentSerialEventTarget
(eventTargetOpenedOn))>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(IsOnCurrentSerialEventTarget
(eventTargetOpenedOn)))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("IsOnCurrentSerialEventTarget(eventTargetOpenedOn)", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2131); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsOnCurrentSerialEventTarget(eventTargetOpenedOn)"
")"); do { *((volatile int*)__null) = 2131; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false); } } while (
false)
;
2132
2133 if (!connectionReady()) {
2134 return NS_ERROR_NOT_INITIALIZED;
2135 }
2136
2137 if (isClosing()) { // Closing already in asynchronous case
2138 return NS_OK;
2139 }
2140
2141 {
2142 // As stated on https://www.sqlite.org/c3ref/interrupt.html,
2143 // it is not safe to call sqlite3_interrupt() when
2144 // database connection is closed or might close before
2145 // sqlite3_interrupt() returns.
2146 MutexAutoLock lockedScope(sharedAsyncExecutionMutex);
2147 if (!isClosed(lockedScope)) {
2148 MOZ_ASSERT(mDBConn)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(mDBConn)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(mDBConn))), 0))) { do { } while
(false); MOZ_ReportAssertionFailure("mDBConn", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2148); AnnotateMozCrashReason("MOZ_ASSERT" "(" "mDBConn" ")"
); do { *((volatile int*)__null) = 2148; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2149 ::sqlite3_interrupt(mDBConn);
2150 }
2151 }
2152
2153 return NS_OK;
2154}
2155
2156NS_IMETHODIMPnsresult
2157Connection::AsyncVacuum(mozIStorageCompletionCallback* aCallback,
2158 bool aUseIncremental, int32_t aSetPageSize) {
2159 NS_ENSURE_TRUE(NS_IsMainThread(), NS_ERROR_NOT_SAME_THREAD)do { if ((__builtin_expect(!!(!(NS_IsMainThread())), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "NS_IsMainThread()" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2159); return NS_ERROR_NOT_SAME_THREAD; } } while (false)
;
2160 // Abort if we're shutting down.
2161 if (AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownConfirmed)) {
2162 return NS_ERROR_ABORT;
2163 }
2164 // Check if AsyncClose or Close were already invoked.
2165 if (!connectionReady()) {
2166 return NS_ERROR_NOT_INITIALIZED;
2167 }
2168 nsresult rv = ensureOperationSupported(ASYNCHRONOUS);
2169 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2170 return rv;
2171 }
2172 nsIEventTarget* asyncThread = getAsyncExecutionTarget();
2173 if (!asyncThread) {
2174 return NS_ERROR_NOT_INITIALIZED;
2175 }
2176
2177 // Create and dispatch our vacuum event to the background thread.
2178 nsCOMPtr<nsIRunnable> vacuumEvent =
2179 new AsyncVacuumEvent(this, aCallback, aUseIncremental, aSetPageSize);
2180 rv = asyncThread->Dispatch(vacuumEvent, NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL);
2181 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2181); return rv; } } while (false)
;
2182
2183 return NS_OK;
2184}
2185
2186NS_IMETHODIMPnsresult
2187Connection::GetDefaultPageSize(int32_t* _defaultPageSize) {
2188 *_defaultPageSize = Service::kDefaultPageSize;
2189 return NS_OK;
2190}
2191
2192NS_IMETHODIMPnsresult
2193Connection::GetConnectionReady(bool* _ready) {
2194 MOZ_ASSERT(IsOnCurrentSerialEventTarget(eventTargetOpenedOn))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(IsOnCurrentSerialEventTarget(eventTargetOpenedOn))>
::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(IsOnCurrentSerialEventTarget(eventTargetOpenedOn))))
, 0))) { do { } while (false); MOZ_ReportAssertionFailure("IsOnCurrentSerialEventTarget(eventTargetOpenedOn)"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2194); AnnotateMozCrashReason("MOZ_ASSERT" "(" "IsOnCurrentSerialEventTarget(eventTargetOpenedOn)"
")"); do { *((volatile int*)__null) = 2194; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2195 *_ready = connectionReady();
2196 return NS_OK;
2197}
2198
2199NS_IMETHODIMPnsresult
2200Connection::GetDatabaseFile(nsIFile** _dbFile) {
2201 if (!connectionReady()) {
2202 return NS_ERROR_NOT_INITIALIZED;
2203 }
2204 nsresult rv = ensureOperationSupported(ASYNCHRONOUS);
2205 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2206 return rv;
2207 }
2208
2209 NS_IF_ADDREF(*_dbFile = mDatabaseFile)ns_if_addref(*_dbFile = mDatabaseFile);
2210
2211 return NS_OK;
2212}
2213
2214NS_IMETHODIMPnsresult
2215Connection::GetLastInsertRowID(int64_t* _id) {
2216 if (!connectionReady()) {
2217 return NS_ERROR_NOT_INITIALIZED;
2218 }
2219 nsresult rv = ensureOperationSupported(SYNCHRONOUS);
2220 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2221 return rv;
2222 }
2223
2224 sqlite_int64 id = ::sqlite3_last_insert_rowid(mDBConn);
2225 *_id = id;
2226
2227 return NS_OK;
2228}
2229
2230NS_IMETHODIMPnsresult
2231Connection::GetAffectedRows(int32_t* _rows) {
2232 if (!connectionReady()) {
2233 return NS_ERROR_NOT_INITIALIZED;
2234 }
2235 nsresult rv = ensureOperationSupported(SYNCHRONOUS);
2236 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2237 return rv;
2238 }
2239
2240 *_rows = ::sqlite3_changes(mDBConn);
2241
2242 return NS_OK;
2243}
2244
2245NS_IMETHODIMPnsresult
2246Connection::GetLastError(int32_t* _error) {
2247 if (!connectionReady()) {
2248 return NS_ERROR_NOT_INITIALIZED;
2249 }
2250 nsresult rv = ensureOperationSupported(SYNCHRONOUS);
2251 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2252 return rv;
2253 }
2254
2255 *_error = ::sqlite3_errcode(mDBConn);
2256
2257 return NS_OK;
2258}
2259
2260NS_IMETHODIMPnsresult
2261Connection::GetLastErrorString(nsACString& _errorString) {
2262 if (!connectionReady()) {
2263 return NS_ERROR_NOT_INITIALIZED;
2264 }
2265 nsresult rv = ensureOperationSupported(SYNCHRONOUS);
2266 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2267 return rv;
2268 }
2269
2270 const char* serr = ::sqlite3_errmsg(mDBConn);
2271 _errorString.Assign(serr);
2272
2273 return NS_OK;
2274}
2275
2276NS_IMETHODIMPnsresult
2277Connection::GetSchemaVersion(int32_t* _version) {
2278 if (!connectionReady()) {
2279 return NS_ERROR_NOT_INITIALIZED;
2280 }
2281 nsresult rv = ensureOperationSupported(SYNCHRONOUS);
2282 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2283 return rv;
2284 }
2285
2286 nsCOMPtr<mozIStorageStatement> stmt;
2287 (void)CreateStatement("PRAGMA user_version"_ns, getter_AddRefs(stmt));
2288 NS_ENSURE_TRUE(stmt, NS_ERROR_OUT_OF_MEMORY)do { if ((__builtin_expect(!!(!(stmt)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "stmt" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2288); return NS_ERROR_OUT_OF_MEMORY; } } while (false)
;
2289
2290 *_version = 0;
2291 bool hasResult;
2292 if (NS_SUCCEEDED(stmt->ExecuteStep(&hasResult))((bool)(__builtin_expect(!!(!NS_FAILED_impl(stmt->ExecuteStep
(&hasResult))), 1)))
&& hasResult) {
2293 *_version = stmt->AsInt32(0);
2294 }
2295
2296 return NS_OK;
2297}
2298
2299NS_IMETHODIMPnsresult
2300Connection::SetSchemaVersion(int32_t aVersion) {
2301 if (!connectionReady()) {
2302 return NS_ERROR_NOT_INITIALIZED;
2303 }
2304 nsresult rv = ensureOperationSupported(SYNCHRONOUS);
2305 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2306 return rv;
2307 }
2308
2309 nsAutoCString stmt("PRAGMA user_version = "_ns);
2310 stmt.AppendInt(aVersion);
2311
2312 return ExecuteSimpleSQL(stmt);
2313}
2314
2315NS_IMETHODIMPnsresult
2316Connection::CreateStatement(const nsACString& aSQLStatement,
2317 mozIStorageStatement** _stmt) {
2318 NS_ENSURE_ARG_POINTER(_stmt)do { if ((__builtin_expect(!!(!(_stmt)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "_stmt" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2318); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2319 if (!connectionReady()) {
2320 return NS_ERROR_NOT_INITIALIZED;
2321 }
2322 nsresult rv = ensureOperationSupported(SYNCHRONOUS);
2323 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2324 return rv;
2325 }
2326
2327 RefPtr<Statement> statement(new Statement());
2328 NS_ENSURE_TRUE(statement, NS_ERROR_OUT_OF_MEMORY)do { if ((__builtin_expect(!!(!(statement)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "statement" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2328); return NS_ERROR_OUT_OF_MEMORY; } } while (false)
;
2329
2330 rv = statement->initialize(this, mDBConn, aSQLStatement);
2331 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2331); return rv; } } while (false)
;
2332
2333 Statement* rawPtr;
2334 statement.forget(&rawPtr);
2335 *_stmt = rawPtr;
2336 return NS_OK;
2337}
2338
2339NS_IMETHODIMPnsresult
2340Connection::CreateAsyncStatement(const nsACString& aSQLStatement,
2341 mozIStorageAsyncStatement** _stmt) {
2342 NS_ENSURE_ARG_POINTER(_stmt)do { if ((__builtin_expect(!!(!(_stmt)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "_stmt" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2342); return NS_ERROR_INVALID_POINTER; } } while (false)
;
2343 if (!connectionReady()) {
2344 return NS_ERROR_NOT_INITIALIZED;
2345 }
2346 nsresult rv = ensureOperationSupported(ASYNCHRONOUS);
2347 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2348 return rv;
2349 }
2350
2351 RefPtr<AsyncStatement> statement(new AsyncStatement());
2352 NS_ENSURE_TRUE(statement, NS_ERROR_OUT_OF_MEMORY)do { if ((__builtin_expect(!!(!(statement)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "statement" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2352); return NS_ERROR_OUT_OF_MEMORY; } } while (false)
;
2353
2354 rv = statement->initialize(this, mDBConn, aSQLStatement);
2355 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2355); return rv; } } while (false)
;
2356
2357 AsyncStatement* rawPtr;
2358 statement.forget(&rawPtr);
2359 *_stmt = rawPtr;
2360 return NS_OK;
2361}
2362
2363NS_IMETHODIMPnsresult
2364Connection::ExecuteSimpleSQL(const nsACString& aSQLStatement) {
2365 CHECK_MAINTHREAD_ABUSE()do { do { if (!(eventTargetOpenedOn == GetMainThreadSerialEventTarget
() || !NS_IsMainThread())) { NS_DebugBreak(NS_DEBUG_WARNING, "Using Storage synchronous API on main-thread, but "
"the connection was opened on another thread.", "eventTargetOpenedOn == GetMainThreadSerialEventTarget() || !NS_IsMainThread()"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2365); } } while (false); } while (0)
;
2366 if (!connectionReady()) {
2367 return NS_ERROR_NOT_INITIALIZED;
2368 }
2369 nsresult rv = ensureOperationSupported(SYNCHRONOUS);
2370 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2371 return rv;
2372 }
2373
2374 int srv = executeSql(mDBConn, PromiseFlatCStringTPromiseFlatString<char>(aSQLStatement).get());
2375 return convertResultCode(srv);
2376}
2377
2378NS_IMETHODIMPnsresult
2379Connection::ExecuteAsync(
2380 const nsTArray<RefPtr<mozIStorageBaseStatement>>& aStatements,
2381 mozIStorageStatementCallback* aCallback,
2382 mozIStoragePendingStatement** _handle) {
2383 nsTArray<StatementData> stmts(aStatements.Length());
2384 for (uint32_t i = 0; i < aStatements.Length(); i++) {
2385 nsCOMPtr<StorageBaseStatementInternal> stmt =
2386 do_QueryInterface(aStatements[i]);
2387 NS_ENSURE_STATE(stmt)do { if ((__builtin_expect(!!(!(stmt)), 0))) { NS_DebugBreak(
NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "stmt" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2387); return NS_ERROR_UNEXPECTED; } } while (false)
;
2388
2389 // Obtain our StatementData.
2390 StatementData data;
2391 nsresult rv = stmt->getAsynchronousStatementData(data);
2392 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2392); return rv; } } while (false)
;
2393
2394 NS_ASSERTION(stmt->getOwner() == this,do { if (!(stmt->getOwner() == this)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Statement must be from this database connection!", "stmt->getOwner() == this"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2395); MOZ_PretendNoReturn(); } } while (0)
2395 "Statement must be from this database connection!")do { if (!(stmt->getOwner() == this)) { NS_DebugBreak(NS_DEBUG_ASSERTION
, "Statement must be from this database connection!", "stmt->getOwner() == this"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2395); MOZ_PretendNoReturn(); } } while (0)
;
2396
2397 // Now append it to our array.
2398 stmts.AppendElement(data);
2399 }
2400
2401 // Dispatch to the background
2402 return AsyncExecuteStatements::execute(std::move(stmts), this, mDBConn,
2403 aCallback, _handle);
2404}
2405
2406NS_IMETHODIMPnsresult
2407Connection::ExecuteSimpleSQLAsync(const nsACString& aSQLStatement,
2408 mozIStorageStatementCallback* aCallback,
2409 mozIStoragePendingStatement** _handle) {
2410 NS_ENSURE_TRUE(NS_IsMainThread(), NS_ERROR_NOT_SAME_THREAD)do { if ((__builtin_expect(!!(!(NS_IsMainThread())), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "NS_IsMainThread()" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2410); return NS_ERROR_NOT_SAME_THREAD; } } while (false)
;
2411
2412 nsCOMPtr<mozIStorageAsyncStatement> stmt;
2413 nsresult rv = CreateAsyncStatement(aSQLStatement, getter_AddRefs(stmt));
2414 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2415 return rv;
2416 }
2417
2418 nsCOMPtr<mozIStoragePendingStatement> pendingStatement;
2419 rv = stmt->ExecuteAsync(aCallback, getter_AddRefs(pendingStatement));
2420 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2421 return rv;
2422 }
2423
2424 pendingStatement.forget(_handle);
2425 return rv;
2426}
2427
2428NS_IMETHODIMPnsresult
2429Connection::TableExists(const nsACString& aTableName, bool* _exists) {
2430 return databaseElementExists(TABLE, aTableName, _exists);
2431}
2432
2433NS_IMETHODIMPnsresult
2434Connection::IndexExists(const nsACString& aIndexName, bool* _exists) {
2435 return databaseElementExists(INDEX, aIndexName, _exists);
2436}
2437
2438NS_IMETHODIMPnsresult
2439Connection::GetTransactionInProgress(bool* _inProgress) {
2440 if (!connectionReady()) {
2441 return NS_ERROR_NOT_INITIALIZED;
2442 }
2443 nsresult rv = ensureOperationSupported(ASYNCHRONOUS);
2444 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2445 return rv;
2446 }
2447
2448 SQLiteMutexAutoLock lockedScope(sharedDBMutex);
2449 *_inProgress = transactionInProgress(lockedScope);
2450 return NS_OK;
2451}
2452
2453NS_IMETHODIMPnsresult
2454Connection::GetDefaultTransactionType(int32_t* _type) {
2455 *_type = mDefaultTransactionType;
2456 return NS_OK;
2457}
2458
2459NS_IMETHODIMPnsresult
2460Connection::SetDefaultTransactionType(int32_t aType) {
2461 NS_ENSURE_ARG_RANGE(aType, TRANSACTION_DEFERRED, TRANSACTION_EXCLUSIVE)do { if ((__builtin_expect(!!(!(((aType) >= TRANSACTION_DEFERRED
) && ((aType) <= TRANSACTION_EXCLUSIVE))), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "((aType) >= TRANSACTION_DEFERRED) && ((aType) <= TRANSACTION_EXCLUSIVE)"
") failed", nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2461); return NS_ERROR_INVALID_ARG; } } while (false)
;
2462 mDefaultTransactionType = aType;
2463 return NS_OK;
2464}
2465
2466NS_IMETHODIMPnsresult
2467Connection::GetVariableLimit(int32_t* _limit) {
2468 if (!connectionReady()) {
2469 return NS_ERROR_NOT_INITIALIZED;
2470 }
2471 int limit = ::sqlite3_limit(mDBConn, SQLITE_LIMIT_VARIABLE_NUMBER9, -1);
2472 if (limit < 0) {
2473 return NS_ERROR_UNEXPECTED;
2474 }
2475 *_limit = limit;
2476 return NS_OK;
2477}
2478
2479NS_IMETHODIMPnsresult
2480Connection::SetVariableLimit(int32_t limit) {
2481 if (!connectionReady()) {
2482 return NS_ERROR_NOT_INITIALIZED;
2483 }
2484 int oldLimit = ::sqlite3_limit(mDBConn, SQLITE_LIMIT_VARIABLE_NUMBER9, limit);
2485 if (oldLimit < 0) {
2486 return NS_ERROR_UNEXPECTED;
2487 }
2488 return NS_OK;
2489}
2490
2491NS_IMETHODIMPnsresult
2492Connection::BeginTransaction() {
2493 if (!connectionReady()) {
2494 return NS_ERROR_NOT_INITIALIZED;
2495 }
2496 nsresult rv = ensureOperationSupported(SYNCHRONOUS);
2497 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2498 return rv;
2499 }
2500
2501 SQLiteMutexAutoLock lockedScope(sharedDBMutex);
2502 return beginTransactionInternal(lockedScope, mDBConn,
2503 mDefaultTransactionType);
2504}
2505
2506nsresult Connection::beginTransactionInternal(
2507 const SQLiteMutexAutoLock& aProofOfLock, sqlite3* aNativeConnection,
2508 int32_t aTransactionType) {
2509 if (transactionInProgress(aProofOfLock)) {
2510 return NS_ERROR_FAILURE;
2511 }
2512 nsresult rv;
2513 switch (aTransactionType) {
2514 case TRANSACTION_DEFERRED:
2515 rv = convertResultCode(executeSql(aNativeConnection, "BEGIN DEFERRED"));
2516 break;
2517 case TRANSACTION_IMMEDIATE:
2518 rv = convertResultCode(executeSql(aNativeConnection, "BEGIN IMMEDIATE"));
2519 break;
2520 case TRANSACTION_EXCLUSIVE:
2521 rv = convertResultCode(executeSql(aNativeConnection, "BEGIN EXCLUSIVE"));
2522 break;
2523 default:
2524 return NS_ERROR_ILLEGAL_VALUE;
2525 }
2526 return rv;
2527}
2528
2529NS_IMETHODIMPnsresult
2530Connection::CommitTransaction() {
2531 if (!connectionReady()) {
2532 return NS_ERROR_NOT_INITIALIZED;
2533 }
2534 nsresult rv = ensureOperationSupported(SYNCHRONOUS);
2535 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2536 return rv;
2537 }
2538
2539 SQLiteMutexAutoLock lockedScope(sharedDBMutex);
2540 return commitTransactionInternal(lockedScope, mDBConn);
2541}
2542
2543nsresult Connection::commitTransactionInternal(
2544 const SQLiteMutexAutoLock& aProofOfLock, sqlite3* aNativeConnection) {
2545 if (!transactionInProgress(aProofOfLock)) {
2546 return NS_ERROR_UNEXPECTED;
2547 }
2548 nsresult rv =
2549 convertResultCode(executeSql(aNativeConnection, "COMMIT TRANSACTION"));
2550 return rv;
2551}
2552
2553NS_IMETHODIMPnsresult
2554Connection::RollbackTransaction() {
2555 if (!connectionReady()) {
2556 return NS_ERROR_NOT_INITIALIZED;
2557 }
2558 nsresult rv = ensureOperationSupported(SYNCHRONOUS);
2559 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2560 return rv;
2561 }
2562
2563 SQLiteMutexAutoLock lockedScope(sharedDBMutex);
2564 return rollbackTransactionInternal(lockedScope, mDBConn);
2565}
2566
2567nsresult Connection::rollbackTransactionInternal(
2568 const SQLiteMutexAutoLock& aProofOfLock, sqlite3* aNativeConnection) {
2569 if (!transactionInProgress(aProofOfLock)) {
2570 return NS_ERROR_UNEXPECTED;
2571 }
2572
2573 nsresult rv =
2574 convertResultCode(executeSql(aNativeConnection, "ROLLBACK TRANSACTION"));
2575 return rv;
2576}
2577
2578NS_IMETHODIMPnsresult
2579Connection::CreateTable(const char* aTableName, const char* aTableSchema) {
2580 if (!connectionReady()) {
2581 return NS_ERROR_NOT_INITIALIZED;
2582 }
2583 nsresult rv = ensureOperationSupported(SYNCHRONOUS);
2584 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2585 return rv;
2586 }
2587
2588 SmprintfPointer buf =
2589 ::mozilla::Smprintf("CREATE TABLE %s (%s)", aTableName, aTableSchema);
2590 if (!buf) return NS_ERROR_OUT_OF_MEMORY;
2591
2592 int srv = executeSql(mDBConn, buf.get());
2593
2594 return convertResultCode(srv);
2595}
2596
2597NS_IMETHODIMPnsresult
2598Connection::CreateFunction(const nsACString& aFunctionName,
2599 int32_t aNumArguments,
2600 mozIStorageFunction* aFunction) {
2601 if (!connectionReady()) {
2602 return NS_ERROR_NOT_INITIALIZED;
2603 }
2604 nsresult rv = ensureOperationSupported(ASYNCHRONOUS);
2605 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2606 return rv;
2607 }
2608
2609 // Check to see if this function is already defined. We only check the name
2610 // because a function can be defined with the same body but different names.
2611 SQLiteMutexAutoLock lockedScope(sharedDBMutex);
2612 NS_ENSURE_FALSE(mFunctions.Contains(aFunctionName), NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(!(mFunctions.Contains(aFunctionName
)))), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE("
"!(mFunctions.Contains(aFunctionName))" ") failed", nullptr,
"/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2612); return NS_ERROR_FAILURE; } } while (false)
;
2613
2614 int srv = ::sqlite3_create_function(
2615 mDBConn, nsPromiseFlatCString(aFunctionName).get(), aNumArguments,
2616 SQLITE_ANY5, aFunction, basicFunctionHelper, nullptr, nullptr);
2617 if (srv != SQLITE_OK0) return convertResultCode(srv);
2618
2619 FunctionInfo info = {aFunction, aNumArguments};
2620 mFunctions.InsertOrUpdate(aFunctionName, info);
2621
2622 return NS_OK;
2623}
2624
2625NS_IMETHODIMPnsresult
2626Connection::RemoveFunction(const nsACString& aFunctionName) {
2627 if (!connectionReady()) {
2628 return NS_ERROR_NOT_INITIALIZED;
2629 }
2630 nsresult rv = ensureOperationSupported(ASYNCHRONOUS);
2631 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2632 return rv;
2633 }
2634
2635 SQLiteMutexAutoLock lockedScope(sharedDBMutex);
2636 NS_ENSURE_TRUE(mFunctions.Get(aFunctionName, nullptr), NS_ERROR_FAILURE)do { if ((__builtin_expect(!!(!(mFunctions.Get(aFunctionName,
nullptr))), 0))) { NS_DebugBreak(NS_DEBUG_WARNING, "NS_ENSURE_TRUE("
"mFunctions.Get(aFunctionName, nullptr)" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2636); return NS_ERROR_FAILURE; } } while (false)
;
2637
2638 int srv = ::sqlite3_create_function(
2639 mDBConn, nsPromiseFlatCString(aFunctionName).get(), 0, SQLITE_ANY5,
2640 nullptr, nullptr, nullptr, nullptr);
2641 if (srv != SQLITE_OK0) return convertResultCode(srv);
2642
2643 mFunctions.Remove(aFunctionName);
2644
2645 return NS_OK;
2646}
2647
2648NS_IMETHODIMPnsresult
2649Connection::SetProgressHandler(int32_t aGranularity,
2650 mozIStorageProgressHandler* aHandler,
2651 mozIStorageProgressHandler** _oldHandler) {
2652 if (!connectionReady()) {
2653 return NS_ERROR_NOT_INITIALIZED;
2654 }
2655 nsresult rv = ensureOperationSupported(ASYNCHRONOUS);
2656 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2657 return rv;
2658 }
2659
2660 // Return previous one
2661 SQLiteMutexAutoLock lockedScope(sharedDBMutex);
2662 NS_IF_ADDREF(*_oldHandler = mProgressHandler)ns_if_addref(*_oldHandler = mProgressHandler);
2663
2664 if (!aHandler || aGranularity <= 0) {
2665 aHandler = nullptr;
2666 aGranularity = 0;
2667 }
2668 mProgressHandler = aHandler;
2669 ::sqlite3_progress_handler(mDBConn, aGranularity, sProgressHelper, this);
2670
2671 return NS_OK;
2672}
2673
2674NS_IMETHODIMPnsresult
2675Connection::RemoveProgressHandler(mozIStorageProgressHandler** _oldHandler) {
2676 if (!connectionReady()) {
2677 return NS_ERROR_NOT_INITIALIZED;
2678 }
2679 nsresult rv = ensureOperationSupported(ASYNCHRONOUS);
2680 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2681 return rv;
2682 }
2683
2684 // Return previous one
2685 SQLiteMutexAutoLock lockedScope(sharedDBMutex);
2686 NS_IF_ADDREF(*_oldHandler = mProgressHandler)ns_if_addref(*_oldHandler = mProgressHandler);
2687
2688 mProgressHandler = nullptr;
2689 ::sqlite3_progress_handler(mDBConn, 0, nullptr, nullptr);
2690
2691 return NS_OK;
2692}
2693
2694NS_IMETHODIMPnsresult
2695Connection::SetGrowthIncrement(int32_t aChunkSize,
2696 const nsACString& aDatabaseName) {
2697 if (!connectionReady()) {
2698 return NS_ERROR_NOT_INITIALIZED;
2699 }
2700 nsresult rv = ensureOperationSupported(SYNCHRONOUS);
2701 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2702 return rv;
2703 }
2704
2705 // Bug 597215: Disk space is extremely limited on Android
2706 // so don't preallocate space. This is also not effective
2707 // on log structured file systems used by Android devices
2708#if !defined(ANDROID) && !defined(MOZ_PLATFORM_MAEMO)
2709 // Don't preallocate if less than 500MiB is available.
2710 int64_t bytesAvailable;
2711 rv = mDatabaseFile->GetDiskSpaceAvailable(&bytesAvailable);
2712 NS_ENSURE_SUCCESS(rv, rv)do { nsresult __rv = rv; if (((bool)(__builtin_expect(!!(NS_FAILED_impl
(__rv)), 0)))) { const char* name = mozilla::GetStaticErrorName
(__rv); mozilla::SmprintfPointer msg = mozilla::Smprintf( "NS_ENSURE_SUCCESS(%s, %s) failed with "
"result 0x%" "X" "%s%s%s", "rv", "rv", static_cast<uint32_t
>(__rv), name ? " (" : "", name ? name : "", name ? ")" : ""
); NS_DebugBreak(NS_DEBUG_WARNING, msg.get(), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2712); return rv; } } while (false)
;
2713 if (bytesAvailable < MIN_AVAILABLE_BYTES_PER_CHUNKED_GROWTH524288000) {
2714 return NS_ERROR_FILE_TOO_BIG;
2715 }
2716
2717 int srv = ::sqlite3_file_control(
2718 mDBConn,
2719 aDatabaseName.Length() ? nsPromiseFlatCString(aDatabaseName).get()
2720 : nullptr,
2721 SQLITE_FCNTL_CHUNK_SIZE6, &aChunkSize);
2722 if (srv == SQLITE_OK0) {
2723 mGrowthChunkSize = aChunkSize;
2724 }
2725#endif
2726 return NS_OK;
2727}
2728
2729int32_t Connection::RemovablePagesInFreeList(const nsACString& aSchemaName) {
2730 int32_t freeListPagesCount = 0;
2731 if (!isConnectionReadyOnThisThread()) {
2732 MOZ_ASSERT(false, "Database connection is not ready")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "Database connection is not ready"
")", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2732); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"Database connection is not ready" ")"); do { *((volatile int
*)__null) = 2732; __attribute__((nomerge)) ::abort(); } while
(false); } } while (false)
;
2733 return freeListPagesCount;
2734 }
2735 {
2736 nsAutoCString query(MOZ_STORAGE_UNIQUIFY_QUERY_STR"/* " "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
" */ "
"PRAGMA ");
2737 query.Append(aSchemaName);
2738 query.AppendLiteral(".freelist_count");
2739 nsCOMPtr<mozIStorageStatement> stmt;
2740 DebugOnly<nsresult> rv = CreateStatement(query, getter_AddRefs(stmt));
2741 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2741); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { *((volatile int*)__null) = 2741; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2742 bool hasResult = false;
2743 if (stmt && NS_SUCCEEDED(stmt->ExecuteStep(&hasResult))((bool)(__builtin_expect(!!(!NS_FAILED_impl(stmt->ExecuteStep
(&hasResult))), 1)))
&& hasResult) {
2744 freeListPagesCount = stmt->AsInt32(0);
2745 }
2746 }
2747 // If there's no chunk size set, any page is good to be removed.
2748 if (mGrowthChunkSize == 0 || freeListPagesCount == 0) {
2749 return freeListPagesCount;
2750 }
2751 int32_t pageSize;
2752 {
2753 nsAutoCString query(MOZ_STORAGE_UNIQUIFY_QUERY_STR"/* " "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
" */ "
"PRAGMA ");
2754 query.Append(aSchemaName);
2755 query.AppendLiteral(".page_size");
2756 nsCOMPtr<mozIStorageStatement> stmt;
2757 DebugOnly<nsresult> rv = CreateStatement(query, getter_AddRefs(stmt));
2758 MOZ_ASSERT(NS_SUCCEEDED(rv))do { static_assert( mozilla::detail::AssertionConditionType<
decltype(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
)))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)
))))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2758); AnnotateMozCrashReason("MOZ_ASSERT" "(" "((bool)(__builtin_expect(!!(!NS_FAILED_impl(rv)), 1)))"
")"); do { *((volatile int*)__null) = 2758; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2759 bool hasResult = false;
2760 if (stmt && NS_SUCCEEDED(stmt->ExecuteStep(&hasResult))((bool)(__builtin_expect(!!(!NS_FAILED_impl(stmt->ExecuteStep
(&hasResult))), 1)))
&& hasResult) {
2761 pageSize = stmt->AsInt32(0);
2762 } else {
2763 MOZ_ASSERT(false, "Couldn't get page_size")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(false)>::isValid, "invalid assertion condition");
if ((__builtin_expect(!!(!(!!(false))), 0))) { do { } while (
false); MOZ_ReportAssertionFailure("false" " (" "Couldn't get page_size"
")", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2763); AnnotateMozCrashReason("MOZ_ASSERT" "(" "false" ") ("
"Couldn't get page_size" ")"); do { *((volatile int*)__null)
= 2763; __attribute__((nomerge)) ::abort(); } while (false);
} } while (false)
;
2764 return 0;
2765 }
2766 }
2767 return std::max(0, freeListPagesCount - (mGrowthChunkSize / pageSize));
2768}
2769
2770NS_IMETHODIMPnsresult
2771Connection::LoadExtension(const nsACString& aExtensionName,
2772 mozIStorageCompletionCallback* aCallback) {
2773 AUTO_PROFILER_LABEL("Connection::LoadExtension", OTHER)mozilla::AutoProfilerLabel raiiObject2773( "Connection::LoadExtension"
, nullptr, JS::ProfilingCategoryPair::OTHER)
;
2774
2775 // This is a static list of extensions we can load.
2776 // Please use lowercase ASCII names and keep this list alphabetically ordered.
2777 static constexpr nsLiteralCString sSupportedExtensions[] = {
2778 // clang-format off
2779 "fts5"_ns,
2780 // clang-format on
2781 };
2782 if (std::find(std::begin(sSupportedExtensions),
2783 std::end(sSupportedExtensions),
2784 aExtensionName) == std::end(sSupportedExtensions)) {
2785 return NS_ERROR_INVALID_ARG;
2786 }
2787
2788 if (!connectionReady()) {
2789 return NS_ERROR_NOT_INITIALIZED;
2790 }
2791
2792 int srv = ::sqlite3_db_config(mDBConn, SQLITE_DBCONFIG_ENABLE_LOAD_EXTENSION1005,
2793 1, nullptr);
2794 if (srv != SQLITE_OK0) {
2795 return NS_ERROR_UNEXPECTED;
2796 }
2797
2798 // Track the loaded extension for later connection cloning operations.
2799 {
2800 MutexAutoLock lockedScope(sharedAsyncExecutionMutex);
2801 if (!mLoadedExtensions.EnsureInserted(aExtensionName)) {
2802 // Already loaded, bail out but issue a warning.
2803 NS_WARNING(nsPrintfCString(NS_DebugBreak(NS_DEBUG_WARNING, nsPrintfCString( "Tried to register '%s' SQLite extension multiple times!"
, TPromiseFlatString<char>(aExtensionName).get()) .get(
), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2806)
2804 "Tried to register '%s' SQLite extension multiple times!",NS_DebugBreak(NS_DEBUG_WARNING, nsPrintfCString( "Tried to register '%s' SQLite extension multiple times!"
, TPromiseFlatString<char>(aExtensionName).get()) .get(
), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2806)
2805 PromiseFlatCString(aExtensionName).get())NS_DebugBreak(NS_DEBUG_WARNING, nsPrintfCString( "Tried to register '%s' SQLite extension multiple times!"
, TPromiseFlatString<char>(aExtensionName).get()) .get(
), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2806)
2806 .get())NS_DebugBreak(NS_DEBUG_WARNING, nsPrintfCString( "Tried to register '%s' SQLite extension multiple times!"
, TPromiseFlatString<char>(aExtensionName).get()) .get(
), nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2806)
;
2807 return NS_OK;
2808 }
2809 }
2810
2811 nsAutoCString entryPoint("sqlite3_");
2812 entryPoint.Append(aExtensionName);
2813 entryPoint.AppendLiteral("_init");
2814
2815 RefPtr<Runnable> loadTask = NS_NewRunnableFunction(
2816 "mozStorageConnection::LoadExtension",
2817 [this, self = RefPtr(this), entryPoint,
2818 callback = RefPtr(aCallback)]() mutable {
2819 MOZ_ASSERT(do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!NS_IsMainThread() || (operationSupported(Connection
::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget
()))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!NS_IsMainThread() || (operationSupported(Connection
::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget
())))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!NS_IsMainThread() || (operationSupported(Connection::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget())"
" (" "Should happen on main-thread only for synchronous connections "
"opened on the main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2824); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!NS_IsMainThread() || (operationSupported(Connection::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget())"
") (" "Should happen on main-thread only for synchronous connections "
"opened on the main thread" ")"); do { *((volatile int*)__null
) = 2824; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
2820 !NS_IsMainThread() ||do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!NS_IsMainThread() || (operationSupported(Connection
::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget
()))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!NS_IsMainThread() || (operationSupported(Connection
::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget
())))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!NS_IsMainThread() || (operationSupported(Connection::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget())"
" (" "Should happen on main-thread only for synchronous connections "
"opened on the main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2824); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!NS_IsMainThread() || (operationSupported(Connection::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget())"
") (" "Should happen on main-thread only for synchronous connections "
"opened on the main thread" ")"); do { *((volatile int*)__null
) = 2824; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
2821 (operationSupported(Connection::SYNCHRONOUS) &&do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!NS_IsMainThread() || (operationSupported(Connection
::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget
()))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!NS_IsMainThread() || (operationSupported(Connection
::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget
())))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!NS_IsMainThread() || (operationSupported(Connection::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget())"
" (" "Should happen on main-thread only for synchronous connections "
"opened on the main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2824); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!NS_IsMainThread() || (operationSupported(Connection::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget())"
") (" "Should happen on main-thread only for synchronous connections "
"opened on the main thread" ")"); do { *((volatile int*)__null
) = 2824; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
2822 eventTargetOpenedOn == GetMainThreadSerialEventTarget()),do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!NS_IsMainThread() || (operationSupported(Connection
::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget
()))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!NS_IsMainThread() || (operationSupported(Connection
::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget
())))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!NS_IsMainThread() || (operationSupported(Connection::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget())"
" (" "Should happen on main-thread only for synchronous connections "
"opened on the main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2824); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!NS_IsMainThread() || (operationSupported(Connection::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget())"
") (" "Should happen on main-thread only for synchronous connections "
"opened on the main thread" ")"); do { *((volatile int*)__null
) = 2824; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
2823 "Should happen on main-thread only for synchronous connections "do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!NS_IsMainThread() || (operationSupported(Connection
::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget
()))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!NS_IsMainThread() || (operationSupported(Connection
::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget
())))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!NS_IsMainThread() || (operationSupported(Connection::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget())"
" (" "Should happen on main-thread only for synchronous connections "
"opened on the main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2824); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!NS_IsMainThread() || (operationSupported(Connection::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget())"
") (" "Should happen on main-thread only for synchronous connections "
"opened on the main thread" ")"); do { *((volatile int*)__null
) = 2824; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
2824 "opened on the main thread")do { static_assert( mozilla::detail::AssertionConditionType<
decltype(!NS_IsMainThread() || (operationSupported(Connection
::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget
()))>::isValid, "invalid assertion condition"); if ((__builtin_expect
(!!(!(!!(!NS_IsMainThread() || (operationSupported(Connection
::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget
())))), 0))) { do { } while (false); MOZ_ReportAssertionFailure
("!NS_IsMainThread() || (operationSupported(Connection::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget())"
" (" "Should happen on main-thread only for synchronous connections "
"opened on the main thread" ")", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2824); AnnotateMozCrashReason("MOZ_ASSERT" "(" "!NS_IsMainThread() || (operationSupported(Connection::SYNCHRONOUS) && eventTargetOpenedOn == GetMainThreadSerialEventTarget())"
") (" "Should happen on main-thread only for synchronous connections "
"opened on the main thread" ")"); do { *((volatile int*)__null
) = 2824; __attribute__((nomerge)) ::abort(); } while (false)
; } } while (false)
;
2825#ifdef MOZ_FOLD_LIBS
2826 int srv = ::sqlite3_load_extension(mDBConn,
2827 MOZ_DLL_PREFIX"lib" "nss3" MOZ_DLL_SUFFIX".so",
2828 entryPoint.get(), nullptr);
2829#else
2830 int srv = ::sqlite3_load_extension(
2831 mDBConn, MOZ_DLL_PREFIX"lib" "mozsqlite3" MOZ_DLL_SUFFIX".so",
2832 entryPoint.get(), nullptr);
2833#endif
2834 if (!callback) {
2835 return;
2836 };
2837 RefPtr<Runnable> callbackTask = NS_NewRunnableFunction(
2838 "mozStorageConnection::LoadExtension_callback",
2839 [callback = std::move(callback), srv]() {
2840 (void)callback->Complete(convertResultCode(srv), nullptr);
2841 });
2842 if (IsOnCurrentSerialEventTarget(eventTargetOpenedOn)) {
2843 MOZ_ALWAYS_SUCCEEDS(callbackTask->Run())do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(callbackTask->Run())), 1)))), 1))) { } else { do { do { }
while (false); MOZ_ReportCrash("" "NS_SUCCEEDED(callbackTask->Run())"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2843); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(callbackTask->Run())"
")"); do { *((volatile int*)__null) = 2843; __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
2844 } else {
2845 // Redispatch the callback to the calling thread.
2846 MOZ_ALWAYS_SUCCEEDS(eventTargetOpenedOn->Dispatch(do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(eventTargetOpenedOn->Dispatch( callbackTask.forget(), nsIEventTarget
::DISPATCH_NORMAL))), 1)))), 1))) { } else { do { do { } while
(false); MOZ_ReportCrash("" "NS_SUCCEEDED(eventTargetOpenedOn->Dispatch( callbackTask.forget(), nsIEventTarget::DISPATCH_NORMAL))"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2847); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(eventTargetOpenedOn->Dispatch( callbackTask.forget(), nsIEventTarget::DISPATCH_NORMAL))"
")"); do { *((volatile int*)__null) = 2847; __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
2847 callbackTask.forget(), NS_DISPATCH_NORMAL))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(eventTargetOpenedOn->Dispatch( callbackTask.forget(), nsIEventTarget
::DISPATCH_NORMAL))), 1)))), 1))) { } else { do { do { } while
(false); MOZ_ReportCrash("" "NS_SUCCEEDED(eventTargetOpenedOn->Dispatch( callbackTask.forget(), nsIEventTarget::DISPATCH_NORMAL))"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2847); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(eventTargetOpenedOn->Dispatch( callbackTask.forget(), nsIEventTarget::DISPATCH_NORMAL))"
")"); do { *((volatile int*)__null) = 2847; __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
2848 }
2849 });
2850
2851 if (NS_IsMainThread() && !operationSupported(Connection::SYNCHRONOUS)) {
2852 // This is a main-thread call to an async-only connection, thus we should
2853 // load the library in the helper thread.
2854 nsIEventTarget* helperThread = getAsyncExecutionTarget();
2855 if (!helperThread) {
2856 return NS_ERROR_NOT_INITIALIZED;
2857 }
2858 MOZ_ALWAYS_SUCCEEDS(do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(helperThread->Dispatch(loadTask.forget(), nsIEventTarget::
DISPATCH_NORMAL))), 1)))), 1))) { } else { do { do { } while (
false); MOZ_ReportCrash("" "NS_SUCCEEDED(helperThread->Dispatch(loadTask.forget(), nsIEventTarget::DISPATCH_NORMAL))"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2859); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(helperThread->Dispatch(loadTask.forget(), nsIEventTarget::DISPATCH_NORMAL))"
")"); do { *((volatile int*)__null) = 2859; __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
2859 helperThread->Dispatch(loadTask.forget(), NS_DISPATCH_NORMAL))do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(helperThread->Dispatch(loadTask.forget(), nsIEventTarget::
DISPATCH_NORMAL))), 1)))), 1))) { } else { do { do { } while (
false); MOZ_ReportCrash("" "NS_SUCCEEDED(helperThread->Dispatch(loadTask.forget(), nsIEventTarget::DISPATCH_NORMAL))"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2859); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(helperThread->Dispatch(loadTask.forget(), nsIEventTarget::DISPATCH_NORMAL))"
")"); do { *((volatile int*)__null) = 2859; __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
2860 } else {
2861 // In any other case we just load the extension on the current thread.
2862 MOZ_ALWAYS_SUCCEEDS(loadTask->Run())do { if ((__builtin_expect(!!(((bool)(__builtin_expect(!!(!NS_FAILED_impl
(loadTask->Run())), 1)))), 1))) { } else { do { do { } while
(false); MOZ_ReportCrash("" "NS_SUCCEEDED(loadTask->Run())"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2862); AnnotateMozCrashReason("MOZ_CRASH(" "NS_SUCCEEDED(loadTask->Run())"
")"); do { *((volatile int*)__null) = 2862; __attribute__((nomerge
)) ::abort(); } while (false); } while (false); } } while (false
)
;
2863 }
2864 return NS_OK;
2865}
2866
2867NS_IMETHODIMPnsresult
2868Connection::EnableModule(const nsACString& aModuleName) {
2869 if (!connectionReady()) {
2870 return NS_ERROR_NOT_INITIALIZED;
2871 }
2872 nsresult rv = ensureOperationSupported(SYNCHRONOUS);
2873 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2874 return rv;
2875 }
2876
2877 for (auto& gModule : gModules) {
2878 struct Module* m = &gModule;
2879 if (aModuleName.Equals(m->name)) {
2880 int srv = m->registerFunc(mDBConn, m->name);
2881 if (srv != SQLITE_OK0) return convertResultCode(srv);
2882
2883 return NS_OK;
2884 }
2885 }
2886
2887 return NS_ERROR_FAILURE;
2888}
2889
2890NS_IMETHODIMPnsresult
2891Connection::GetQuotaObjects(QuotaObject** aDatabaseQuotaObject,
2892 QuotaObject** aJournalQuotaObject) {
2893 MOZ_ASSERT(aDatabaseQuotaObject)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aDatabaseQuotaObject)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aDatabaseQuotaObject))), 0))
) { do { } while (false); MOZ_ReportAssertionFailure("aDatabaseQuotaObject"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2893); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aDatabaseQuotaObject"
")"); do { *((volatile int*)__null) = 2893; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2894 MOZ_ASSERT(aJournalQuotaObject)do { static_assert( mozilla::detail::AssertionConditionType<
decltype(aJournalQuotaObject)>::isValid, "invalid assertion condition"
); if ((__builtin_expect(!!(!(!!(aJournalQuotaObject))), 0)))
{ do { } while (false); MOZ_ReportAssertionFailure("aJournalQuotaObject"
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2894); AnnotateMozCrashReason("MOZ_ASSERT" "(" "aJournalQuotaObject"
")"); do { *((volatile int*)__null) = 2894; __attribute__((nomerge
)) ::abort(); } while (false); } } while (false)
;
2895
2896 if (!connectionReady()) {
2897 return NS_ERROR_NOT_INITIALIZED;
2898 }
2899 nsresult rv = ensureOperationSupported(SYNCHRONOUS);
2900 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2901 return rv;
2902 }
2903
2904 sqlite3_file* file;
2905 int srv = ::sqlite3_file_control(mDBConn, nullptr, SQLITE_FCNTL_FILE_POINTER7,
2906 &file);
2907 if (srv != SQLITE_OK0) {
2908 return convertResultCode(srv);
2909 }
2910
2911 sqlite3_vfs* vfs;
2912 srv =
2913 ::sqlite3_file_control(mDBConn, nullptr, SQLITE_FCNTL_VFS_POINTER27, &vfs);
2914 if (srv != SQLITE_OK0) {
2915 return convertResultCode(srv);
2916 }
2917
2918 bool obfusactingVFS = false;
2919
2920 {
2921 const nsDependentCString vfsName{vfs->zName};
2922
2923 if (vfsName == obfsvfs::GetVFSName()) {
2924 obfusactingVFS = true;
2925 } else if (vfsName != quotavfs::GetVFSName()) {
2926 NS_WARNING("Got unexpected vfs")NS_DebugBreak(NS_DEBUG_WARNING, "Got unexpected vfs", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2926)
;
2927 return NS_ERROR_FAILURE;
2928 }
2929 }
2930
2931 RefPtr<QuotaObject> databaseQuotaObject =
2932 GetQuotaObject(file, obfusactingVFS);
2933 if (NS_WARN_IF(!databaseQuotaObject)NS_warn_if_impl(!databaseQuotaObject, "!databaseQuotaObject",
"/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2933)
) {
2934 return NS_ERROR_FAILURE;
2935 }
2936
2937 srv = ::sqlite3_file_control(mDBConn, nullptr, SQLITE_FCNTL_JOURNAL_POINTER28,
2938 &file);
2939 if (srv != SQLITE_OK0) {
2940 return convertResultCode(srv);
2941 }
2942
2943 RefPtr<QuotaObject> journalQuotaObject = GetQuotaObject(file, obfusactingVFS);
2944 if (NS_WARN_IF(!journalQuotaObject)NS_warn_if_impl(!journalQuotaObject, "!journalQuotaObject", "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2944)
) {
2945 return NS_ERROR_FAILURE;
2946 }
2947
2948 databaseQuotaObject.forget(aDatabaseQuotaObject);
2949 journalQuotaObject.forget(aJournalQuotaObject);
2950 return NS_OK;
2951}
2952
2953SQLiteMutex& Connection::GetSharedDBMutex() { return sharedDBMutex; }
2954
2955uint32_t Connection::GetTransactionNestingLevel(
2956 const mozilla::storage::SQLiteMutexAutoLock& aProofOfLock) {
2957 return mTransactionNestingLevel;
2958}
2959
2960uint32_t Connection::IncreaseTransactionNestingLevel(
2961 const mozilla::storage::SQLiteMutexAutoLock& aProofOfLock) {
2962 return ++mTransactionNestingLevel;
2963}
2964
2965uint32_t Connection::DecreaseTransactionNestingLevel(
2966 const mozilla::storage::SQLiteMutexAutoLock& aProofOfLock) {
2967 return --mTransactionNestingLevel;
2968}
2969
2970NS_IMETHODIMPnsresult
2971Connection::BackupToFileAsync(nsIFile* aDestinationFile,
2972 mozIStorageCompletionCallback* aCallback,
2973 uint32_t aPagesPerStep, uint32_t aStepDelayMs) {
2974 NS_ENSURE_ARG(aDestinationFile)do { if ((__builtin_expect(!!(!(aDestinationFile)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aDestinationFile" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2974); return NS_ERROR_INVALID_ARG; } } while (false)
;
2975 NS_ENSURE_ARG(aCallback)do { if ((__builtin_expect(!!(!(aCallback)), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "aCallback" ") failed", nullptr
, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2975); return NS_ERROR_INVALID_ARG; } } while (false)
;
2976 NS_ENSURE_TRUE(NS_IsMainThread(), NS_ERROR_NOT_SAME_THREAD)do { if ((__builtin_expect(!!(!(NS_IsMainThread())), 0))) { NS_DebugBreak
(NS_DEBUG_WARNING, "NS_ENSURE_TRUE(" "NS_IsMainThread()" ") failed"
, nullptr, "/var/lib/jenkins/workspace/firefox-scan-build/storage/mozStorageConnection.cpp"
, 2976); return NS_ERROR_NOT_SAME_THREAD; } } while (false)
;
2977
2978 // Abort if we're shutting down.
2979 if (AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownConfirmed)) {
2980 return NS_ERROR_ABORT;
2981 }
2982 // Check if AsyncClose or Close were already invoked.
2983 if (!connectionReady()) {
2984 return NS_ERROR_NOT_INITIALIZED;
2985 }
2986 nsresult rv = ensureOperationSupported(ASYNCHRONOUS);
2987 if (NS_FAILED(rv)((bool)(__builtin_expect(!!(NS_FAILED_impl(rv)), 0)))) {
2988 return rv;
2989 }
2990 nsIEventTarget* asyncThread = getAsyncExecutionTarget();
2991 if (!asyncThread) {
2992 return NS_ERROR_NOT_INITIALIZED;
2993 }
2994
2995 // The number of pages of the database to copy per step
2996 static constexpr int32_t DEFAULT_PAGES_PER_STEP = 5;
2997 // The number of milliseconds to wait between each step.
2998 static constexpr uint32_t DEFAULT_STEP_DELAY_MS = 250;
2999
3000 CheckedInt<int32_t> pagesPerStep(aPagesPerStep);
3001 if (!pagesPerStep.isValid()) {
3002 return NS_ERROR_INVALID_ARG;
3003 }
3004
3005 if (!pagesPerStep.value()) {
3006 pagesPerStep = DEFAULT_PAGES_PER_STEP;
3007 }
3008
3009 if (!aStepDelayMs) {
3010 aStepDelayMs = DEFAULT_STEP_DELAY_MS;
3011 }
3012
3013 // Create and dispatch our backup event to the execution thread.
3014 nsCOMPtr<nsIRunnable> backupEvent =
3015 new AsyncBackupDatabaseFile(this, mDBConn, aDestinationFile, aCallback,
3016 pagesPerStep.value(), aStepDelayMs);
3017 rv = asyncThread->Dispatch(backupEvent, NS_DISPATCH_NORMALnsIEventTarget::DISPATCH_NORMAL);
3018 return rv;
3019}
3020
3021} // namespace mozilla::storage