1 | /* |
2 | * Copyright (C) 2007, 2008, 2013 Apple Inc. All rights reserved. |
3 | * |
4 | * Redistribution and use in source and binary forms, with or without |
5 | * modification, are permitted provided that the following conditions |
6 | * are met: |
7 | * |
8 | * 1. Redistributions of source code must retain the above copyright |
9 | * notice, this list of conditions and the following disclaimer. |
10 | * 2. Redistributions in binary form must reproduce the above copyright |
11 | * notice, this list of conditions and the following disclaimer in the |
12 | * documentation and/or other materials provided with the distribution. |
13 | * 3. Neither the name of Apple Inc. ("Apple") nor the names of |
14 | * its contributors may be used to endorse or promote products derived |
15 | * from this software without specific prior written permission. |
16 | * |
17 | * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY |
18 | * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
19 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
20 | * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY |
21 | * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
22 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
23 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND |
24 | * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
25 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
26 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
27 | */ |
28 | |
29 | #include "config.h" |
30 | #include "SQLTransactionBackend.h" |
31 | |
32 | #include "Database.h" |
33 | #include "DatabaseAuthorizer.h" |
34 | #include "DatabaseContext.h" |
35 | #include "DatabaseThread.h" |
36 | #include "DatabaseTracker.h" |
37 | #include "Logging.h" |
38 | #include "OriginLock.h" |
39 | #include "SQLError.h" |
40 | #include "SQLStatement.h" |
41 | #include "SQLStatementCallback.h" |
42 | #include "SQLStatementErrorCallback.h" |
43 | #include "SQLTransaction.h" |
44 | #include "SQLTransactionCoordinator.h" |
45 | #include "SQLiteTransaction.h" |
46 | #include <wtf/StdLibExtras.h> |
47 | #include <wtf/text/WTFString.h> |
48 | |
49 | |
50 | // How does a SQLTransaction work? |
51 | // ============================== |
52 | // The SQLTransaction is a state machine that executes a series of states / steps. |
53 | // |
54 | // The work of the transaction states are defined in section of 4.3.2 of the |
55 | // webdatabase spec: http://dev.w3.org/html5/webdatabase/#processing-model |
56 | // |
57 | // the State Transition Graph at a glance: |
58 | // ====================================== |
59 | // |
60 | // Backend . Frontend |
61 | // (works with SQLiteDatabase) . (works with Script) |
62 | // =========================== . =================== |
63 | // . |
64 | // 1. Idle . |
65 | // v . |
66 | // 2. AcquireLock . |
67 | // v . |
68 | // 3. OpenTransactionAndPreflight ------------------------------------------. |
69 | // | . | |
70 | // `-------------------------------> 8. DeliverTransactionCallback --. | |
71 | // . | v v |
72 | // ,-------------------------------------' 9. DeliverTransactionErrorCallback + |
73 | // | . ^ ^ ^ | |
74 | // v . | | | | |
75 | // 4. RunStatements -----------------------------------------------------' | | | |
76 | // | ^ ^ | ^ | . | | | |
77 | // |--------' | | | `------------> 10. DeliverStatementCallback +-----' | | |
78 | // | | | `---------------------------------------------' | | |
79 | // | | `-----------------> 11. DeliverQuotaIncreaseCallback + | | |
80 | // | `-----------------------------------------------------' | | |
81 | // v . | | |
82 | // 5. PostflightAndCommit --+--------------------------------------------------' | |
83 | // |----------> 12. DeliverSuccessCallback + | |
84 | // ,--------------------' . | | |
85 | // v . | | |
86 | // 6. CleanupAndTerminate <-----------------------------------------' | |
87 | // v ^ . | |
88 | // 0. End | . | |
89 | // | . | |
90 | // 7: CleanupAfterTransactionErrorCallback <----------------------------' |
91 | // . |
92 | // |
93 | // the States and State Transitions: |
94 | // ================================ |
95 | // 0. SQLTransactionState::End |
96 | // - the end state. |
97 | // |
98 | // 1. SQLTransactionState::Idle |
99 | // - placeholder state while waiting on frontend/backend, etc. See comment on |
100 | // "State transitions between SQLTransaction and SQLTransactionBackend" |
101 | // below. |
102 | // |
103 | // 2. SQLTransactionState::AcquireLock (runs in backend) |
104 | // - this is the start state. |
105 | // - acquire the "lock". |
106 | // - on "lock" acquisition, goto SQLTransactionState::OpenTransactionAndPreflight. |
107 | // |
108 | // 3. SQLTransactionState::openTransactionAndPreflight (runs in backend) |
109 | // - Sets up an SQLiteTransaction. |
110 | // - begin the SQLiteTransaction. |
111 | // - call the SQLTransactionWrapper preflight if available. |
112 | // - schedule script callback. |
113 | // - on error, goto SQLTransactionState::DeliverTransactionErrorCallback. |
114 | // - goto SQLTransactionState::DeliverTransactionCallback. |
115 | // |
116 | // 4. SQLTransactionState::DeliverTransactionCallback (runs in frontend) |
117 | // - invoke the script function callback() if available. |
118 | // - on error, goto SQLTransactionState::DeliverTransactionErrorCallback. |
119 | // - goto SQLTransactionState::RunStatements. |
120 | // |
121 | // 5. SQLTransactionState::DeliverTransactionErrorCallback (runs in frontend) |
122 | // - invoke the script function errorCallback if available. |
123 | // - goto SQLTransactionState::CleanupAfterTransactionErrorCallback. |
124 | // |
125 | // 6. SQLTransactionState::RunStatements (runs in backend) |
126 | // - while there are statements { |
127 | // - run a statement. |
128 | // - if statementCallback is available, goto SQLTransactionState::DeliverStatementCallback. |
129 | // - on error, |
130 | // goto SQLTransactionState::DeliverQuotaIncreaseCallback, or |
131 | // goto SQLTransactionState::DeliverStatementCallback, or |
132 | // goto SQLTransactionState::deliverTransactionErrorCallback. |
133 | // } |
134 | // - goto SQLTransactionState::PostflightAndCommit. |
135 | // |
136 | // 7. SQLTransactionState::DeliverStatementCallback (runs in frontend) |
137 | // - invoke script statement callback (assume available). |
138 | // - on error, goto SQLTransactionState::DeliverTransactionErrorCallback. |
139 | // - goto SQLTransactionState::RunStatements. |
140 | // |
141 | // 8. SQLTransactionState::DeliverQuotaIncreaseCallback (runs in frontend) |
142 | // - give client a chance to increase the quota. |
143 | // - goto SQLTransactionState::RunStatements. |
144 | // |
145 | // 9. SQLTransactionState::PostflightAndCommit (runs in backend) |
146 | // - call the SQLTransactionWrapper postflight if available. |
147 | // - commit the SQLiteTansaction. |
148 | // - on error, goto SQLTransactionState::DeliverTransactionErrorCallback. |
149 | // - if successCallback is available, goto SQLTransactionState::DeliverSuccessCallback. |
150 | // else goto SQLTransactionState::CleanupAndTerminate. |
151 | // |
152 | // 10. SQLTransactionState::DeliverSuccessCallback (runs in frontend) |
153 | // - invoke the script function successCallback() if available. |
154 | // - goto SQLTransactionState::CleanupAndTerminate. |
155 | // |
156 | // 11. SQLTransactionState::CleanupAndTerminate (runs in backend) |
157 | // - stop and clear the SQLiteTransaction. |
158 | // - release the "lock". |
159 | // - goto SQLTransactionState::End. |
160 | // |
161 | // 12. SQLTransactionState::CleanupAfterTransactionErrorCallback (runs in backend) |
162 | // - rollback the SQLiteTransaction. |
163 | // - goto SQLTransactionState::CleanupAndTerminate. |
164 | // |
165 | // State transitions between SQLTransaction and SQLTransactionBackend |
166 | // ================================================================== |
167 | // As shown above, there are state transitions that crosses the boundary between |
168 | // the frontend and backend. For example, |
169 | // |
170 | // OpenTransactionAndPreflight (state 3 in the backend) |
171 | // transitions to DeliverTransactionCallback (state 8 in the frontend), |
172 | // which in turn transitions to RunStatements (state 4 in the backend). |
173 | // |
174 | // This cross boundary transition is done by posting transition requests to the |
175 | // other side and letting the other side's state machine execute the state |
176 | // transition in the appropriate thread (i.e. the script thread for the frontend, |
177 | // and the database thread for the backend). |
178 | // |
179 | // Logically, the state transitions work as shown in the graph above. But |
180 | // physically, the transition mechanism uses the Idle state (both in the frontend |
181 | // and backend) as a waiting state for further activity. For example, taking a |
182 | // closer look at the 3 state transition example above, what actually happens |
183 | // is as follows: |
184 | // |
185 | // Step 1: |
186 | // ====== |
187 | // In the frontend thread: |
188 | // - waiting quietly is Idle. Not doing any work. |
189 | // |
190 | // In the backend: |
191 | // - is in OpenTransactionAndPreflight, and doing its work. |
192 | // - when done, it transits to the backend DeliverTransactionCallback. |
193 | // - the backend DeliverTransactionCallback sends a request to the frontend |
194 | // to transit to DeliverTransactionCallback, and then itself transits to |
195 | // Idle. |
196 | // |
197 | // Step 2: |
198 | // ====== |
199 | // In the frontend thread: |
200 | // - transits to DeliverTransactionCallback and does its work. |
201 | // - when done, it transits to the frontend RunStatements. |
202 | // - the frontend RunStatements sends a request to the backend to transit |
203 | // to RunStatements, and then itself transits to Idle. |
204 | // |
205 | // In the backend: |
206 | // - waiting quietly in Idle. |
207 | // |
208 | // Step 3: |
209 | // ====== |
210 | // In the frontend thread: |
211 | // - waiting quietly is Idle. Not doing any work. |
212 | // |
213 | // In the backend: |
214 | // - transits to RunStatements, and does its work. |
215 | // ... |
216 | // |
217 | // So, when the frontend or backend are not active, they will park themselves in |
218 | // their Idle states. This means their m_nextState is set to Idle, but they never |
219 | // actually run the corresponding state function. Note: for both the frontend and |
220 | // backend, the state function for Idle is unreachableState(). |
221 | // |
222 | // The states that send a request to their peer across the front/back boundary |
223 | // are implemented with just 2 functions: SQLTransaction::sendToBackendState() |
224 | // and SQLTransactionBackend::sendToFrontendState(). These state functions do |
225 | // nothing but sends a request to the other side to transit to the current |
226 | // state (indicated by m_nextState), and then transits itself to the Idle state |
227 | // to wait for further action. |
228 | |
229 | |
230 | // The Life-Cycle of a SQLTransaction i.e. Who's keeping the SQLTransaction alive? |
231 | // ============================================================================== |
232 | // The RefPtr chain goes something like this: |
233 | // |
234 | // At birth (in DatabaseBackend::runTransaction()): |
235 | // ==================================================== |
236 | // DatabaseBackend // Deque<RefPtr<SQLTransactionBackend>> m_transactionQueue points to ... |
237 | // --> SQLTransactionBackend // RefPtr<SQLTransaction> m_frontend points to ... |
238 | // --> SQLTransaction // RefPtr<SQLTransactionBackend> m_backend points to ... |
239 | // --> SQLTransactionBackend // which is a circular reference. |
240 | // |
241 | // Note: there's a circular reference between the SQLTransaction front-end and |
242 | // back-end. This circular reference is established in the constructor of the |
243 | // SQLTransactionBackend. The circular reference will be broken by calling |
244 | // doCleanup() to nullify m_frontend. This is done at the end of the transaction's |
245 | // clean up state (i.e. when the transaction should no longer be in use thereafter), |
246 | // or if the database was interrupted. See comments on "What happens if a transaction |
247 | // is interrupted?" below for details. |
248 | // |
249 | // After scheduling the transaction with the DatabaseThread (DatabaseBackend::scheduleTransaction()): |
250 | // ====================================================================================================== |
251 | // DatabaseThread // MessageQueue<DatabaseTask> m_queue points to ... |
252 | // --> DatabaseTransactionTask // RefPtr<SQLTransactionBackend> m_transaction points to ... |
253 | // --> SQLTransactionBackend // RefPtr<SQLTransaction> m_frontend points to ... |
254 | // --> SQLTransaction // RefPtr<SQLTransactionBackend> m_backend points to ... |
255 | // --> SQLTransactionBackend // which is a circular reference. |
256 | // |
257 | // When executing the transaction (in DatabaseThread::databaseThread()): |
258 | // ==================================================================== |
259 | // std::unique_ptr<DatabaseTask> task; // points to ... |
260 | // --> DatabaseTransactionTask // RefPtr<SQLTransactionBackend> m_transaction points to ... |
261 | // --> SQLTransactionBackend // RefPtr<SQLTransaction> m_frontend; |
262 | // --> SQLTransaction // RefPtr<SQLTransactionBackend> m_backend points to ... |
263 | // --> SQLTransactionBackend // which is a circular reference. |
264 | // |
265 | // At the end of cleanupAndTerminate(): |
266 | // =================================== |
267 | // At the end of the cleanup state, the SQLTransactionBackend::m_frontend is nullified. |
268 | // If by then, a JSObject wrapper is referring to the SQLTransaction, then the reference |
269 | // chain looks like this: |
270 | // |
271 | // JSObjectWrapper |
272 | // --> SQLTransaction // in RefPtr<SQLTransactionBackend> m_backend points to ... |
273 | // --> SQLTransactionBackend // which no longer points back to its SQLTransaction. |
274 | // |
275 | // When the GC collects the corresponding JSObject, the above chain will be cleaned up |
276 | // and deleted. |
277 | // |
278 | // If there is no JSObject wrapper referring to the SQLTransaction when the cleanup |
279 | // states nullify SQLTransactionBackend::m_frontend, the SQLTransaction will deleted then. |
280 | // However, there will still be a DatabaseTask pointing to the SQLTransactionBackend (see |
281 | // the "When executing the transaction" chain above). This will keep the |
282 | // SQLTransactionBackend alive until DatabaseThread::databaseThread() releases its |
283 | // task std::unique_ptr. |
284 | // |
285 | // What happens if a transaction is interrupted? |
286 | // ============================================ |
287 | // If the transaction is interrupted half way, it won't get to run to state |
288 | // CleanupAndTerminate, and hence, would not have called SQLTransactionBackend's |
289 | // doCleanup(). doCleanup() is where we nullify SQLTransactionBackend::m_frontend |
290 | // to break the reference cycle between the frontend and backend. Hence, we need |
291 | // to cleanup the transaction by other means. |
292 | // |
293 | // Note: calling SQLTransactionBackend::notifyDatabaseThreadIsShuttingDown() |
294 | // is effectively the same as calling SQLTransactionBackend::doClean(). |
295 | // |
296 | // In terms of who needs to call doCleanup(), there are 5 phases in the |
297 | // SQLTransactionBackend life-cycle. These are the phases and how the clean |
298 | // up is done: |
299 | // |
300 | // Phase 1. After Birth, before scheduling |
301 | // |
302 | // - To clean up, DatabaseThread::databaseThread() will call |
303 | // DatabaseBackend::close() during its shutdown. |
304 | // - DatabaseBackend::close() will iterate |
305 | // DatabaseBackend::m_transactionQueue and call |
306 | // notifyDatabaseThreadIsShuttingDown() on each transaction there. |
307 | // |
308 | // Phase 2. After scheduling, before state AcquireLock |
309 | // |
310 | // - If the interruption occures before the DatabaseTransactionTask is |
311 | // scheduled in DatabaseThread::m_queue but hasn't gotten to execute |
312 | // (i.e. DatabaseTransactionTask::performTask() has not been called), |
313 | // then the DatabaseTransactionTask may get destructed before it ever |
314 | // gets to execute. |
315 | // - To clean up, the destructor will check if the task's m_wasExecuted is |
316 | // set. If not, it will call notifyDatabaseThreadIsShuttingDown() on |
317 | // the task's transaction. |
318 | // |
319 | // Phase 3. After state AcquireLock, before "lockAcquired" |
320 | // |
321 | // - In this phase, the transaction would have been added to the |
322 | // SQLTransactionCoordinator's CoordinationInfo's pendingTransactions. |
323 | // - To clean up, during shutdown, DatabaseThread::databaseThread() calls |
324 | // SQLTransactionCoordinator::shutdown(), which calls |
325 | // notifyDatabaseThreadIsShuttingDown(). |
326 | // |
327 | // Phase 4: After "lockAcquired", before state CleanupAndTerminate |
328 | // |
329 | // - In this phase, the transaction would have been added either to the |
330 | // SQLTransactionCoordinator's CoordinationInfo's activeWriteTransaction |
331 | // or activeReadTransactions. |
332 | // - To clean up, during shutdown, DatabaseThread::databaseThread() calls |
333 | // SQLTransactionCoordinator::shutdown(), which calls |
334 | // notifyDatabaseThreadIsShuttingDown(). |
335 | // |
336 | // Phase 5: After state CleanupAndTerminate |
337 | // |
338 | // - This is how a transaction ends normally. |
339 | // - state CleanupAndTerminate calls doCleanup(). |
340 | |
341 | namespace WebCore { |
342 | |
343 | SQLTransactionBackend::SQLTransactionBackend(SQLTransaction& frontend) |
344 | : m_frontend(frontend) |
345 | { |
346 | m_requestedState = SQLTransactionState::AcquireLock; |
347 | } |
348 | |
349 | SQLTransactionBackend::~SQLTransactionBackend() |
350 | { |
351 | ASSERT(!m_frontend.m_sqliteTransaction); |
352 | } |
353 | |
354 | void SQLTransactionBackend::doCleanup() |
355 | { |
356 | ASSERT(m_frontend.database().databaseThread().getThread() == &Thread::current()); |
357 | |
358 | m_frontend.releaseOriginLockIfNeeded(); |
359 | |
360 | LockHolder locker(m_frontend.m_statementMutex); |
361 | m_frontend.m_statementQueue.clear(); |
362 | |
363 | if (m_frontend.m_sqliteTransaction) { |
364 | // In the event we got here because of an interruption or error (i.e. if |
365 | // the transaction is in progress), we should roll it back here. Clearing |
366 | // m_sqliteTransaction invokes SQLiteTransaction's destructor which does |
367 | // just that. We might as well do this unconditionally and free up its |
368 | // resources because we're already terminating. |
369 | m_frontend.m_sqliteTransaction = nullptr; |
370 | } |
371 | |
372 | // Release the lock on this database |
373 | if (m_frontend.m_lockAcquired) |
374 | m_frontend.m_database->transactionCoordinator()->releaseLock(m_frontend); |
375 | |
376 | // Do some aggresive clean up here except for m_database. |
377 | // |
378 | // We can't clear m_database here because the frontend may asynchronously |
379 | // invoke SQLTransactionBackend::requestTransitToState(), and that function |
380 | // uses m_database to schedule a state transition. This may occur because |
381 | // the frontend (being in another thread) may already be on the way to |
382 | // requesting our next state before it detects an interruption. |
383 | // |
384 | // There is no harm in letting it finish making the request. It'll set |
385 | // m_requestedState, but we won't execute a transition to that state because |
386 | // we've already shut down the transaction. |
387 | // |
388 | // We also can't clear m_currentStatementBackend and m_transactionError. |
389 | // m_currentStatementBackend may be accessed asynchronously by the |
390 | // frontend's deliverStatementCallback() state. Similarly, |
391 | // m_transactionError may be accessed by deliverTransactionErrorCallback(). |
392 | // This occurs if requests for transition to those states have already been |
393 | // registered with the frontend just prior to a clean up request arriving. |
394 | // |
395 | // So instead, let our destructor handle their clean up since this |
396 | // SQLTransactionBackend is guaranteed to not destruct until the frontend |
397 | // is also destructing. |
398 | |
399 | m_frontend.m_wrapper = nullptr; |
400 | } |
401 | |
402 | SQLTransactionBackend::StateFunction SQLTransactionBackend::stateFunctionFor(SQLTransactionState state) |
403 | { |
404 | static const StateFunction stateFunctions[] = { |
405 | &SQLTransactionBackend::unreachableState, // 0. end |
406 | &SQLTransactionBackend::unreachableState, // 1. idle |
407 | &SQLTransactionBackend::acquireLock, // 2. |
408 | &SQLTransactionBackend::openTransactionAndPreflight, // 3. |
409 | &SQLTransactionBackend::runStatements, // 4. |
410 | &SQLTransactionBackend::unreachableState, // 5. postflightAndCommit |
411 | &SQLTransactionBackend::cleanupAndTerminate, // 6. |
412 | &SQLTransactionBackend::cleanupAfterTransactionErrorCallback, // 7. |
413 | &SQLTransactionBackend::unreachableState, // 8. deliverTransactionCallback |
414 | &SQLTransactionBackend::unreachableState, // 9. deliverTransactionErrorCallback |
415 | &SQLTransactionBackend::unreachableState, // 10. deliverStatementCallback |
416 | &SQLTransactionBackend::unreachableState, // 11. deliverQuotaIncreaseCallback |
417 | &SQLTransactionBackend::unreachableState // 12. deliverSuccessCallback |
418 | }; |
419 | |
420 | ASSERT(WTF_ARRAY_LENGTH(stateFunctions) == static_cast<int>(SQLTransactionState::NumberOfStates)); |
421 | ASSERT(state < SQLTransactionState::NumberOfStates); |
422 | |
423 | return stateFunctions[static_cast<int>(state)]; |
424 | } |
425 | |
426 | void SQLTransactionBackend::computeNextStateAndCleanupIfNeeded() |
427 | { |
428 | // Only honor the requested state transition if we're not supposed to be |
429 | // cleaning up and shutting down: |
430 | if (m_frontend.m_database->opened()) { |
431 | setStateToRequestedState(); |
432 | ASSERT(m_nextState == SQLTransactionState::AcquireLock |
433 | || m_nextState == SQLTransactionState::OpenTransactionAndPreflight |
434 | || m_nextState == SQLTransactionState::RunStatements |
435 | || m_nextState == SQLTransactionState::PostflightAndCommit |
436 | || m_nextState == SQLTransactionState::CleanupAndTerminate |
437 | || m_nextState == SQLTransactionState::CleanupAfterTransactionErrorCallback); |
438 | |
439 | LOG(StorageAPI, "State %s\n" , nameForSQLTransactionState(m_nextState)); |
440 | return; |
441 | } |
442 | |
443 | // If we get here, then we should be shutting down. Do clean up if needed: |
444 | if (m_nextState == SQLTransactionState::End) |
445 | return; |
446 | m_nextState = SQLTransactionState::End; |
447 | |
448 | // If the database was stopped, don't do anything and cancel queued work |
449 | LOG(StorageAPI, "Database was stopped or interrupted - cancelling work for this transaction" ); |
450 | |
451 | // The current SQLite transaction should be stopped, as well |
452 | if (m_frontend.m_sqliteTransaction) { |
453 | m_frontend.m_sqliteTransaction->stop(); |
454 | m_frontend.m_sqliteTransaction = nullptr; |
455 | } |
456 | |
457 | // Terminate the frontend state machine. This also gets the frontend to |
458 | // call computeNextStateAndCleanupIfNeeded() and clear its wrappers |
459 | // if needed. |
460 | m_frontend.requestTransitToState(SQLTransactionState::End); |
461 | |
462 | // Redirect to the end state to abort, clean up, and end the transaction. |
463 | doCleanup(); |
464 | } |
465 | |
466 | void SQLTransactionBackend::notifyDatabaseThreadIsShuttingDown() |
467 | { |
468 | ASSERT(m_frontend.database().databaseThread().getThread() == &Thread::current()); |
469 | |
470 | // If the transaction is in progress, we should roll it back here, since this |
471 | // is our last opportunity to do something related to this transaction on the |
472 | // DB thread. Amongst other work, doCleanup() will clear m_sqliteTransaction |
473 | // which invokes SQLiteTransaction's destructor, which will do the roll back |
474 | // if necessary. |
475 | doCleanup(); |
476 | } |
477 | |
478 | void SQLTransactionBackend::acquireLock() |
479 | { |
480 | m_frontend.acquireLock(); |
481 | } |
482 | |
483 | void SQLTransactionBackend::openTransactionAndPreflight() |
484 | { |
485 | m_frontend.openTransactionAndPreflight(); |
486 | } |
487 | |
488 | void SQLTransactionBackend::runStatements() |
489 | { |
490 | m_frontend.runStatements(); |
491 | } |
492 | |
493 | void SQLTransactionBackend::cleanupAndTerminate() |
494 | { |
495 | m_frontend.cleanupAndTerminate(); |
496 | } |
497 | |
498 | void SQLTransactionBackend::cleanupAfterTransactionErrorCallback() |
499 | { |
500 | m_frontend.cleanupAfterTransactionErrorCallback(); |
501 | } |
502 | |
503 | // requestTransitToState() can be called from the frontend. Hence, it should |
504 | // NOT be modifying SQLTransactionBackend in general. The only safe field to |
505 | // modify is m_requestedState which is meant for this purpose. |
506 | void SQLTransactionBackend::requestTransitToState(SQLTransactionState nextState) |
507 | { |
508 | LOG(StorageAPI, "Scheduling %s for transaction %p\n" , nameForSQLTransactionState(nextState), this); |
509 | m_requestedState = nextState; |
510 | ASSERT(m_requestedState != SQLTransactionState::End); |
511 | m_frontend.m_database->scheduleTransactionStep(m_frontend); |
512 | } |
513 | |
514 | // This state function is used as a stub function to plug unimplemented states |
515 | // in the state dispatch table. They are unimplemented because they should |
516 | // never be reached in the course of correct execution. |
517 | void SQLTransactionBackend::unreachableState() |
518 | { |
519 | ASSERT_NOT_REACHED(); |
520 | } |
521 | |
522 | } // namespace WebCore |
523 | |