CachingDatabaseConnection.cpp (5857B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 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 file, 5 * You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #include "mozilla/dom/quota/CachingDatabaseConnection.h" 8 9 #include "mozilla/GeckoTrace.h" 10 #include "mozilla/ProfilerLabels.h" 11 #include "mozilla/ipc/BackgroundParent.h" 12 13 namespace mozilla::dom::quota { 14 15 CachingDatabaseConnection::CachingDatabaseConnection( 16 MovingNotNull<nsCOMPtr<mozIStorageConnection>> aStorageConnection) 17 : 18 #ifdef MOZ_THREAD_SAFETY_OWNERSHIP_CHECKS_SUPPORTED 19 mOwningEventTarget{nsAutoOwningEventTarget{}}, 20 #endif 21 mStorageConnection(std::move(aStorageConnection)) { 22 } 23 24 void CachingDatabaseConnection::LazyInit( 25 MovingNotNull<nsCOMPtr<mozIStorageConnection>> aStorageConnection) { 26 #ifdef MOZ_THREAD_SAFETY_OWNERSHIP_CHECKS_SUPPORTED 27 mOwningEventTarget.init(); 28 #endif 29 mStorageConnection.init(std::move(aStorageConnection)); 30 } 31 32 Result<CachingDatabaseConnection::CachedStatement, nsresult> 33 CachingDatabaseConnection::GetCachedStatement(const nsACString& aQuery) { 34 GECKO_TRACE_SCOPE("dom::quota", 35 "CachingDatabaseConnection::GetCachedStatement"); 36 37 AssertIsOnConnectionThread(); 38 MOZ_ASSERT(!aQuery.IsEmpty()); 39 MOZ_ASSERT(mStorageConnection); 40 41 AUTO_PROFILER_LABEL("CachingDatabaseConnection::GetCachedStatement", DOM); 42 43 QM_TRY_UNWRAP( 44 auto stmt, 45 mCachedStatements.TryLookupOrInsertWith( 46 aQuery, [&]() -> Result<nsCOMPtr<mozIStorageStatement>, nsresult> { 47 const auto extraInfo = ScopedLogExtraInfo{ 48 ScopedLogExtraInfo::kTagQueryTainted, aQuery}; 49 50 QM_TRY_RETURN( 51 MOZ_TO_RESULT_INVOKE_MEMBER_TYPED( 52 nsCOMPtr<mozIStorageStatement>, **mStorageConnection, 53 CreateStatement, aQuery), 54 QM_PROPAGATE, 55 ([&aQuery, 56 &storageConnection = **mStorageConnection](const auto&) { 57 #ifdef DEBUG 58 nsCString msg; 59 MOZ_ALWAYS_SUCCEEDS( 60 storageConnection.GetLastErrorString(msg)); 61 62 nsAutoCString error = 63 "The statement '"_ns + aQuery + 64 "' failed to compile with the error message '"_ns + msg + 65 "'."_ns; 66 67 NS_WARNING(error.get()); 68 #else 69 (void)aQuery; 70 #endif 71 })); 72 })); 73 74 return CachedStatement{this, std::move(stmt), aQuery}; 75 } 76 77 Result<CachingDatabaseConnection::BorrowedStatement, nsresult> 78 CachingDatabaseConnection::BorrowCachedStatement(const nsACString& aQuery) { 79 QM_TRY_UNWRAP(auto cachedStatement, GetCachedStatement(aQuery)); 80 81 return cachedStatement.Borrow(); 82 } 83 84 nsresult CachingDatabaseConnection::ExecuteCachedStatement( 85 const nsACString& aQuery) { 86 return ExecuteCachedStatement( 87 aQuery, [](auto&) -> Result<Ok, nsresult> { return Ok{}; }); 88 } 89 90 void CachingDatabaseConnection::Close() { 91 AssertIsOnConnectionThread(); 92 MOZ_ASSERT(HasStorageConnection()); 93 94 AUTO_PROFILER_LABEL("CachingDatabaseConnection::Close", DOM); 95 96 mCachedStatements.Clear(); 97 98 MOZ_ALWAYS_SUCCEEDS((*mStorageConnection)->Close()); 99 mStorageConnection.destroy(); 100 101 mClosed = true; 102 } 103 104 #if defined(DEBUG) || defined(NS_BUILD_REFCNT_LOGGING) 105 CachingDatabaseConnection::CachedStatement::CachedStatement() 106 # ifdef DEBUG 107 : mDEBUGConnection(nullptr) 108 # endif 109 { 110 AssertIsOnConnectionThread(); 111 112 MOZ_COUNT_CTOR(CachingDatabaseConnection::CachedStatement); 113 } 114 115 CachingDatabaseConnection::CachedStatement::~CachedStatement() { 116 AssertIsOnConnectionThread(); 117 118 MOZ_COUNT_DTOR(CachingDatabaseConnection::CachedStatement); 119 } 120 #endif 121 122 CachingDatabaseConnection::CachedStatement::operator bool() const { 123 AssertIsOnConnectionThread(); 124 125 return mStatement; 126 } 127 128 mozIStorageStatement& CachingDatabaseConnection::BorrowedStatement::operator*() 129 const { 130 return *operator->(); 131 } 132 133 mozIStorageStatement* CachingDatabaseConnection::BorrowedStatement::operator->() 134 const { 135 MOZ_ASSERT(mStatement); 136 137 return mStatement; 138 } 139 140 CachingDatabaseConnection::BorrowedStatement 141 CachingDatabaseConnection::CachedStatement::Borrow() const { 142 AssertIsOnConnectionThread(); 143 144 #ifdef QM_SCOPED_LOG_EXTRA_INFO_ENABLED 145 return BorrowedStatement{WrapNotNull(mStatement), mQuery}; 146 #else 147 return BorrowedStatement{WrapNotNull(mStatement)}; 148 #endif 149 } 150 151 CachingDatabaseConnection::CachedStatement::CachedStatement( 152 CachingDatabaseConnection* aConnection, 153 nsCOMPtr<mozIStorageStatement> aStatement, const nsACString& aQuery) 154 : mStatement(std::move(aStatement)) 155 #ifdef QM_SCOPED_LOG_EXTRA_INFO_ENABLED 156 , 157 mQuery(aQuery) 158 #endif 159 #if defined(DEBUG) 160 , 161 mDEBUGConnection(aConnection) 162 #endif 163 { 164 #ifdef DEBUG 165 MOZ_ASSERT(aConnection); 166 aConnection->AssertIsOnConnectionThread(); 167 #endif 168 MOZ_ASSERT(mStatement); 169 AssertIsOnConnectionThread(); 170 171 MOZ_COUNT_CTOR(CachingDatabaseConnection::CachedStatement); 172 } 173 174 void CachingDatabaseConnection::CachedStatement::AssertIsOnConnectionThread() 175 const { 176 #ifdef DEBUG 177 if (mDEBUGConnection) { 178 mDEBUGConnection->AssertIsOnConnectionThread(); 179 } 180 MOZ_ASSERT(!NS_IsMainThread()); 181 MOZ_ASSERT(!mozilla::ipc::IsOnBackgroundThread()); 182 #endif 183 } 184 185 Result<CachingDatabaseConnection::BorrowedStatement, nsresult> 186 CachingDatabaseConnection::LazyStatement::Borrow() { 187 if (!mCachedStatement) { 188 QM_TRY(Initialize()); 189 } 190 191 return mCachedStatement.Borrow(); 192 } 193 194 Result<Ok, nsresult> CachingDatabaseConnection::LazyStatement::Initialize() { 195 QM_TRY_UNWRAP(mCachedStatement, mConnection.GetCachedStatement(mQueryString)); 196 return Ok{}; 197 } 198 199 } // namespace mozilla::dom::quota