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 Computer, 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 "modules/webdatabase/SQLTransactionBackend.h" 31 32#include "modules/webdatabase/Database.h" 33#include "modules/webdatabase/DatabaseAuthorizer.h" 34#include "modules/webdatabase/DatabaseContext.h" 35#include "modules/webdatabase/DatabaseThread.h" 36#include "modules/webdatabase/DatabaseTracker.h" 37#include "modules/webdatabase/SQLError.h" 38#include "modules/webdatabase/SQLStatementBackend.h" 39#include "modules/webdatabase/SQLTransaction.h" 40#include "modules/webdatabase/SQLTransactionClient.h" 41#include "modules/webdatabase/SQLTransactionCoordinator.h" 42#include "modules/webdatabase/sqlite/SQLValue.h" 43#include "modules/webdatabase/sqlite/SQLiteTransaction.h" 44#include "platform/Logging.h" 45#include "wtf/StdLibExtras.h" 46 47 48// How does a SQLTransaction work? 49// ============================== 50// The SQLTransaction is a state machine that executes a series of states / steps. 51// 52// The work of the transaction states are defined in section of 4.3.2 of the 53// webdatabase spec: http://dev.w3.org/html5/webdatabase/#processing-model 54// 55// the State Transition Graph at a glance: 56// ====================================== 57// 58// Backend . Frontend 59// (works with SQLiteDatabase) . (works with Script) 60// =========================== . =================== 61// . 62// 1. Idle . 63// v . 64// 2. AcquireLock . 65// v . 66// 3. OpenTransactionAndPreflight ------------------------------------------. 67// | . | 68// `-------------------------------> 8. DeliverTransactionCallback --. | 69// . | v v 70// ,-------------------------------------' 9. DeliverTransactionErrorCallback + 71// | . ^ ^ ^ | 72// v . | | | | 73// 4. RunStatements -----------------------------------------------------' | | | 74// | ^ ^ | ^ | . | | | 75// |--------' | | | `------------> 10. DeliverStatementCallback +-----' | | 76// | | | `---------------------------------------------' | | 77// | | `-----------------> 11. DeliverQuotaIncreaseCallback + | | 78// | `-----------------------------------------------------' | | 79// v . | | 80// 5. PostflightAndCommit --+--------------------------------------------------' | 81// |----------> 12. DeliverSuccessCallback + | 82// ,--------------------' . | | 83// v . | | 84// 6. CleanupAndTerminate <-----------------------------------------' | 85// v ^ . | 86// 0. End | . | 87// | . | 88// 7: CleanupAfterTransactionErrorCallback <----------------------------' 89// . 90// 91// the States and State Transitions: 92// ================================ 93// 0. SQLTransactionState::End 94// - the end state. 95// 96// 1. SQLTransactionState::Idle 97// - placeholder state while waiting on frontend/backend, etc. See comment on 98// "State transitions between SQLTransaction and SQLTransactionBackend" 99// below. 100// 101// 2. SQLTransactionState::AcquireLock (runs in backend) 102// - this is the start state. 103// - acquire the "lock". 104// - on "lock" acquisition, goto SQLTransactionState::OpenTransactionAndPreflight. 105// 106// 3. SQLTransactionState::openTransactionAndPreflight (runs in backend) 107// - Sets up an SQLiteTransaction. 108// - begin the SQLiteTransaction. 109// - call the SQLTransactionWrapper preflight if available. 110// - schedule script callback. 111// - on error, goto SQLTransactionState::DeliverTransactionErrorCallback. 112// - goto SQLTransactionState::DeliverTransactionCallback. 113// 114// 4. SQLTransactionState::DeliverTransactionCallback (runs in frontend) 115// - invoke the script function callback() if available. 116// - on error, goto SQLTransactionState::DeliverTransactionErrorCallback. 117// - goto SQLTransactionState::RunStatements. 118// 119// 5. SQLTransactionState::DeliverTransactionErrorCallback (runs in frontend) 120// - invoke the script function errorCallback if available. 121// - goto SQLTransactionState::CleanupAfterTransactionErrorCallback. 122// 123// 6. SQLTransactionState::RunStatements (runs in backend) 124// - while there are statements { 125// - run a statement. 126// - if statementCallback is available, goto SQLTransactionState::DeliverStatementCallback. 127// - on error, 128// goto SQLTransactionState::DeliverQuotaIncreaseCallback, or 129// goto SQLTransactionState::DeliverStatementCallback, or 130// goto SQLTransactionState::deliverTransactionErrorCallback. 131// } 132// - goto SQLTransactionState::PostflightAndCommit. 133// 134// 7. SQLTransactionState::DeliverStatementCallback (runs in frontend) 135// - invoke script statement callback (assume available). 136// - on error, goto SQLTransactionState::DeliverTransactionErrorCallback. 137// - goto SQLTransactionState::RunStatements. 138// 139// 8. SQLTransactionState::DeliverQuotaIncreaseCallback (runs in frontend) 140// - give client a chance to increase the quota. 141// - goto SQLTransactionState::RunStatements. 142// 143// 9. SQLTransactionState::PostflightAndCommit (runs in backend) 144// - call the SQLTransactionWrapper postflight if available. 145// - commit the SQLiteTansaction. 146// - on error, goto SQLTransactionState::DeliverTransactionErrorCallback. 147// - if successCallback is available, goto SQLTransactionState::DeliverSuccessCallback. 148// else goto SQLTransactionState::CleanupAndTerminate. 149// 150// 10. SQLTransactionState::DeliverSuccessCallback (runs in frontend) 151// - invoke the script function successCallback() if available. 152// - goto SQLTransactionState::CleanupAndTerminate. 153// 154// 11. SQLTransactionState::CleanupAndTerminate (runs in backend) 155// - stop and clear the SQLiteTransaction. 156// - release the "lock". 157// - goto SQLTransactionState::End. 158// 159// 12. SQLTransactionState::CleanupAfterTransactionErrorCallback (runs in backend) 160// - rollback the SQLiteTransaction. 161// - goto SQLTransactionState::CleanupAndTerminate. 162// 163// State transitions between SQLTransaction and SQLTransactionBackend 164// ================================================================== 165// As shown above, there are state transitions that crosses the boundary between 166// the frontend and backend. For example, 167// 168// OpenTransactionAndPreflight (state 3 in the backend) 169// transitions to DeliverTransactionCallback (state 8 in the frontend), 170// which in turn transitions to RunStatements (state 4 in the backend). 171// 172// This cross boundary transition is done by posting transition requests to the 173// other side and letting the other side's state machine execute the state 174// transition in the appropriate thread (i.e. the script thread for the frontend, 175// and the database thread for the backend). 176// 177// Logically, the state transitions work as shown in the graph above. But 178// physically, the transition mechanism uses the Idle state (both in the frontend 179// and backend) as a waiting state for further activity. For example, taking a 180// closer look at the 3 state transition example above, what actually happens 181// is as follows: 182// 183// Step 1: 184// ====== 185// In the frontend thread: 186// - waiting quietly is Idle. Not doing any work. 187// 188// In the backend: 189// - is in OpenTransactionAndPreflight, and doing its work. 190// - when done, it transits to the backend DeliverTransactionCallback. 191// - the backend DeliverTransactionCallback sends a request to the frontend 192// to transit to DeliverTransactionCallback, and then itself transits to 193// Idle. 194// 195// Step 2: 196// ====== 197// In the frontend thread: 198// - transits to DeliverTransactionCallback and does its work. 199// - when done, it transits to the frontend RunStatements. 200// - the frontend RunStatements sends a request to the backend to transit 201// to RunStatements, and then itself transits to Idle. 202// 203// In the backend: 204// - waiting quietly in Idle. 205// 206// Step 3: 207// ====== 208// In the frontend thread: 209// - waiting quietly is Idle. Not doing any work. 210// 211// In the backend: 212// - transits to RunStatements, and does its work. 213// ... 214// 215// So, when the frontend or backend are not active, they will park themselves in 216// their Idle states. This means their m_nextState is set to Idle, but they never 217// actually run the corresponding state function. Note: for both the frontend and 218// backend, the state function for Idle is unreachableState(). 219// 220// The states that send a request to their peer across the front/back boundary 221// are implemented with just 2 functions: SQLTransaction::sendToBackendState() 222// and SQLTransactionBackend::sendToFrontendState(). These state functions do 223// nothing but sends a request to the other side to transit to the current 224// state (indicated by m_nextState), and then transits itself to the Idle state 225// to wait for further action. 226 227 228// The Life-Cycle of a SQLTransaction i.e. Who's keeping the SQLTransaction alive? 229// ============================================================================== 230// The RefPtr chain goes something like this: 231// 232// At birth (in Database::runTransaction()): 233// ==================================================== 234// Database // Deque<RefPtr<SQLTransactionBackend> > m_transactionQueue points to ... 235// --> SQLTransactionBackend // RefPtr<SQLTransaction> m_frontend points to ... 236// --> SQLTransaction // RefPtr<SQLTransactionBackend> m_backend points to ... 237// --> SQLTransactionBackend // which is a circular reference. 238// 239// Note: there's a circular reference between the SQLTransaction front-end and 240// back-end. This circular reference is established in the constructor of the 241// SQLTransactionBackend. The circular reference will be broken by calling 242// doCleanup() to nullify m_frontend. This is done at the end of the transaction's 243// clean up state (i.e. when the transaction should no longer be in use thereafter), 244// or if the database was interrupted. See comments on "What happens if a transaction 245// is interrupted?" below for details. 246// 247// After scheduling the transaction with the DatabaseThread (Database::scheduleTransaction()): 248// ====================================================================================================== 249// DatabaseThread // MessageQueue<DatabaseTask> m_queue points to ... 250// --> DatabaseTransactionTask // RefPtr<SQLTransactionBackend> m_transaction points to ... 251// --> SQLTransactionBackend // RefPtr<SQLTransaction> m_frontend points to ... 252// --> SQLTransaction // RefPtr<SQLTransactionBackend> m_backend points to ... 253// --> SQLTransactionBackend // which is a circular reference. 254// 255// When executing the transaction (in DatabaseThread::databaseThread()): 256// ==================================================================== 257// OwnPtr<DatabaseTask> task; // points to ... 258// --> DatabaseTransactionTask // RefPtr<SQLTransactionBackend> m_transaction points to ... 259// --> SQLTransactionBackend // RefPtr<SQLTransaction> m_frontend; 260// --> SQLTransaction // RefPtr<SQLTransactionBackend> m_backend points to ... 261// --> SQLTransactionBackend // which is a circular reference. 262// 263// At the end of cleanupAndTerminate(): 264// =================================== 265// At the end of the cleanup state, the SQLTransactionBackend::m_frontend is nullified. 266// If by then, a JSObject wrapper is referring to the SQLTransaction, then the reference 267// chain looks like this: 268// 269// JSObjectWrapper 270// --> SQLTransaction // in RefPtr<SQLTransactionBackend> m_backend points to ... 271// --> SQLTransactionBackend // which no longer points back to its SQLTransaction. 272// 273// When the GC collects the corresponding JSObject, the above chain will be cleaned up 274// and deleted. 275// 276// If there is no JSObject wrapper referring to the SQLTransaction when the cleanup 277// states nullify SQLTransactionBackend::m_frontend, the SQLTransaction will deleted then. 278// However, there will still be a DatabaseTask pointing to the SQLTransactionBackend (see 279// the "When executing the transaction" chain above). This will keep the 280// SQLTransactionBackend alive until DatabaseThread::databaseThread() releases its 281// task OwnPtr. 282// 283// What happens if a transaction is interrupted? 284// ============================================ 285// If the transaction is interrupted half way, it won't get to run to state 286// CleanupAndTerminate, and hence, would not have called SQLTransactionBackend's 287// doCleanup(). doCleanup() is where we nullify SQLTransactionBackend::m_frontend 288// to break the reference cycle between the frontend and backend. Hence, we need 289// to cleanup the transaction by other means. 290// 291// Note: calling SQLTransactionBackend::notifyDatabaseThreadIsShuttingDown() 292// is effectively the same as calling SQLTransactionBackend::doClean(). 293// 294// In terms of who needs to call doCleanup(), there are 5 phases in the 295// SQLTransactionBackend life-cycle. These are the phases and how the clean 296// up is done: 297// 298// Phase 1. After Birth, before scheduling 299// 300// - To clean up, DatabaseThread::databaseThread() will call 301// Database::close() during its shutdown. 302// - Database::close() will iterate 303// Database::m_transactionQueue and call 304// notifyDatabaseThreadIsShuttingDown() on each transaction there. 305// 306// Phase 2. After scheduling, before state AcquireLock 307// 308// - If the interruption occures before the DatabaseTransactionTask is 309// scheduled in DatabaseThread::m_queue but hasn't gotten to execute 310// (i.e. DatabaseTransactionTask::performTask() has not been called), 311// then the DatabaseTransactionTask may get destructed before it ever 312// gets to execute. 313// - To clean up, the destructor will check if the task's m_wasExecuted is 314// set. If not, it will call notifyDatabaseThreadIsShuttingDown() on 315// the task's transaction. 316// 317// Phase 3. After state AcquireLock, before "lockAcquired" 318// 319// - In this phase, the transaction would have been added to the 320// SQLTransactionCoordinator's CoordinationInfo's pendingTransactions. 321// - To clean up, during shutdown, DatabaseThread::databaseThread() calls 322// SQLTransactionCoordinator::shutdown(), which calls 323// notifyDatabaseThreadIsShuttingDown(). 324// 325// Phase 4: After "lockAcquired", before state CleanupAndTerminate 326// 327// - In this phase, the transaction would have been added either to the 328// SQLTransactionCoordinator's CoordinationInfo's activeWriteTransaction 329// or activeReadTransactions. 330// - To clean up, during shutdown, DatabaseThread::databaseThread() calls 331// SQLTransactionCoordinator::shutdown(), which calls 332// notifyDatabaseThreadIsShuttingDown(). 333// 334// Phase 5: After state CleanupAndTerminate 335// 336// - This is how a transaction ends normally. 337// - state CleanupAndTerminate calls doCleanup(). 338 339 340namespace blink { 341 342PassRefPtrWillBeRawPtr<SQLTransactionBackend> SQLTransactionBackend::create(Database* db, 343 PassRefPtrWillBeRawPtr<SQLTransaction> frontend, 344 PassRefPtrWillBeRawPtr<SQLTransactionWrapper> wrapper, 345 bool readOnly) 346{ 347 return adoptRefWillBeNoop(new SQLTransactionBackend(db, frontend, wrapper, readOnly)); 348} 349 350SQLTransactionBackend::SQLTransactionBackend(Database* db, 351 PassRefPtrWillBeRawPtr<SQLTransaction> frontend, 352 PassRefPtrWillBeRawPtr<SQLTransactionWrapper> wrapper, 353 bool readOnly) 354 : m_frontend(frontend) 355 , m_database(db) 356 , m_wrapper(wrapper) 357 , m_hasCallback(m_frontend->hasCallback()) 358 , m_hasSuccessCallback(m_frontend->hasSuccessCallback()) 359 , m_hasErrorCallback(m_frontend->hasErrorCallback()) 360 , m_shouldRetryCurrentStatement(false) 361 , m_modifiedDatabase(false) 362 , m_lockAcquired(false) 363 , m_readOnly(readOnly) 364 , m_hasVersionMismatch(false) 365{ 366 ASSERT(m_database); 367 m_frontend->setBackend(this); 368 m_requestedState = SQLTransactionState::AcquireLock; 369} 370 371SQLTransactionBackend::~SQLTransactionBackend() 372{ 373 ASSERT(!m_sqliteTransaction); 374} 375 376void SQLTransactionBackend::trace(Visitor* visitor) 377{ 378 visitor->trace(m_frontend); 379 visitor->trace(m_currentStatementBackend); 380 visitor->trace(m_database); 381 visitor->trace(m_wrapper); 382 visitor->trace(m_statementQueue); 383} 384 385void SQLTransactionBackend::doCleanup() 386{ 387 if (!m_frontend) 388 return; 389 m_frontend = nullptr; // Break the reference cycle. See comment about the life-cycle above. 390 391 ASSERT(database()->databaseContext()->databaseThread()->isDatabaseThread()); 392 393 MutexLocker locker(m_statementMutex); 394 m_statementQueue.clear(); 395 396 if (m_sqliteTransaction) { 397 // In the event we got here because of an interruption or error (i.e. if 398 // the transaction is in progress), we should roll it back here. Clearing 399 // m_sqliteTransaction invokes SQLiteTransaction's destructor which does 400 // just that. We might as well do this unconditionally and free up its 401 // resources because we're already terminating. 402 m_sqliteTransaction.clear(); 403 } 404 405 // Release the lock on this database 406 if (m_lockAcquired) 407 m_database->transactionCoordinator()->releaseLock(this); 408 409 // Do some aggresive clean up here except for m_database. 410 // 411 // We can't clear m_database here because the frontend may asynchronously 412 // invoke SQLTransactionBackend::requestTransitToState(), and that function 413 // uses m_database to schedule a state transition. This may occur because 414 // the frontend (being in another thread) may already be on the way to 415 // requesting our next state before it detects an interruption. 416 // 417 // There is no harm in letting it finish making the request. It'll set 418 // m_requestedState, but we won't execute a transition to that state because 419 // we've already shut down the transaction. 420 // 421 // We also can't clear m_currentStatementBackend and m_transactionError. 422 // m_currentStatementBackend may be accessed asynchronously by the 423 // frontend's deliverStatementCallback() state. Similarly, 424 // m_transactionError may be accessed by deliverTransactionErrorCallback(). 425 // This occurs if requests for transition to those states have already been 426 // registered with the frontend just prior to a clean up request arriving. 427 // 428 // So instead, let our destructor handle their clean up since this 429 // SQLTransactionBackend is guaranteed to not destruct until the frontend 430 // is also destructing. 431 432 m_wrapper = nullptr; 433} 434 435SQLStatement* SQLTransactionBackend::currentStatement() 436{ 437 return m_currentStatementBackend->frontend(); 438} 439 440SQLErrorData* SQLTransactionBackend::transactionError() 441{ 442 return m_transactionError.get(); 443} 444 445void SQLTransactionBackend::setShouldRetryCurrentStatement(bool shouldRetry) 446{ 447 ASSERT(!m_shouldRetryCurrentStatement); 448 m_shouldRetryCurrentStatement = shouldRetry; 449} 450 451SQLTransactionBackend::StateFunction SQLTransactionBackend::stateFunctionFor(SQLTransactionState state) 452{ 453 static const StateFunction stateFunctions[] = { 454 &SQLTransactionBackend::unreachableState, // 0. end 455 &SQLTransactionBackend::unreachableState, // 1. idle 456 &SQLTransactionBackend::acquireLock, // 2. 457 &SQLTransactionBackend::openTransactionAndPreflight, // 3. 458 &SQLTransactionBackend::runStatements, // 4. 459 &SQLTransactionBackend::postflightAndCommit, // 5. 460 &SQLTransactionBackend::cleanupAndTerminate, // 6. 461 &SQLTransactionBackend::cleanupAfterTransactionErrorCallback, // 7. 462 &SQLTransactionBackend::sendToFrontendState, // 8. deliverTransactionCallback 463 &SQLTransactionBackend::sendToFrontendState, // 9. deliverTransactionErrorCallback 464 &SQLTransactionBackend::sendToFrontendState, // 10. deliverStatementCallback 465 &SQLTransactionBackend::sendToFrontendState, // 11. deliverQuotaIncreaseCallback 466 &SQLTransactionBackend::sendToFrontendState // 12. deliverSuccessCallback 467 }; 468 469 ASSERT(WTF_ARRAY_LENGTH(stateFunctions) == static_cast<int>(SQLTransactionState::NumberOfStates)); 470 ASSERT(state < SQLTransactionState::NumberOfStates); 471 472 return stateFunctions[static_cast<int>(state)]; 473} 474 475void SQLTransactionBackend::enqueueStatementBackend(PassRefPtrWillBeRawPtr<SQLStatementBackend> statementBackend) 476{ 477 MutexLocker locker(m_statementMutex); 478 m_statementQueue.append(statementBackend); 479} 480 481void SQLTransactionBackend::computeNextStateAndCleanupIfNeeded() 482{ 483 // Only honor the requested state transition if we're not supposed to be 484 // cleaning up and shutting down: 485 if (m_database->opened()) { 486 setStateToRequestedState(); 487 ASSERT(m_nextState == SQLTransactionState::AcquireLock 488 || m_nextState == SQLTransactionState::OpenTransactionAndPreflight 489 || m_nextState == SQLTransactionState::RunStatements 490 || m_nextState == SQLTransactionState::PostflightAndCommit 491 || m_nextState == SQLTransactionState::CleanupAndTerminate 492 || m_nextState == SQLTransactionState::CleanupAfterTransactionErrorCallback); 493 494 WTF_LOG(StorageAPI, "State %s\n", nameForSQLTransactionState(m_nextState)); 495 return; 496 } 497 498 // If we get here, then we should be shutting down. Do clean up if needed: 499 if (m_nextState == SQLTransactionState::End) 500 return; 501 m_nextState = SQLTransactionState::End; 502 503 // If the database was stopped, don't do anything and cancel queued work 504 WTF_LOG(StorageAPI, "Database was stopped or interrupted - cancelling work for this transaction"); 505 506 // The current SQLite transaction should be stopped, as well 507 if (m_sqliteTransaction) { 508 m_sqliteTransaction->stop(); 509 m_sqliteTransaction.clear(); 510 } 511 512 // Terminate the frontend state machine. This also gets the frontend to 513 // call computeNextStateAndCleanupIfNeeded() and clear its wrappers 514 // if needed. 515 m_frontend->requestTransitToState(SQLTransactionState::End); 516 517 // Redirect to the end state to abort, clean up, and end the transaction. 518 doCleanup(); 519} 520 521void SQLTransactionBackend::performNextStep() 522{ 523 computeNextStateAndCleanupIfNeeded(); 524 runStateMachine(); 525} 526 527void SQLTransactionBackend::executeSQL(PassOwnPtrWillBeRawPtr<SQLStatement> statement, 528 const String& sqlStatement, const Vector<SQLValue>& arguments, int permissions) 529{ 530 enqueueStatementBackend(SQLStatementBackend::create(statement, sqlStatement, arguments, permissions)); 531} 532 533void SQLTransactionBackend::notifyDatabaseThreadIsShuttingDown() 534{ 535 ASSERT(database()->databaseContext()->databaseThread()->isDatabaseThread()); 536 537 // If the transaction is in progress, we should roll it back here, since this 538 // is our last opportunity to do something related to this transaction on the 539 // DB thread. Amongst other work, doCleanup() will clear m_sqliteTransaction 540 // which invokes SQLiteTransaction's destructor, which will do the roll back 541 // if necessary. 542 doCleanup(); 543} 544 545SQLTransactionState SQLTransactionBackend::acquireLock() 546{ 547 m_database->transactionCoordinator()->acquireLock(this); 548 return SQLTransactionState::Idle; 549} 550 551void SQLTransactionBackend::lockAcquired() 552{ 553 m_lockAcquired = true; 554 requestTransitToState(SQLTransactionState::OpenTransactionAndPreflight); 555} 556 557SQLTransactionState SQLTransactionBackend::openTransactionAndPreflight() 558{ 559 ASSERT(!m_database->sqliteDatabase().transactionInProgress()); 560 ASSERT(m_lockAcquired); 561 562 WTF_LOG(StorageAPI, "Opening and preflighting transaction %p", this); 563 564 // Set the maximum usage for this transaction if this transactions is not read-only 565 if (!m_readOnly) 566 m_database->sqliteDatabase().setMaximumSize(m_database->maximumSize()); 567 568 ASSERT(!m_sqliteTransaction); 569 m_sqliteTransaction = adoptPtr(new SQLiteTransaction(m_database->sqliteDatabase(), m_readOnly)); 570 571 m_database->resetDeletes(); 572 m_database->disableAuthorizer(); 573 m_sqliteTransaction->begin(); 574 m_database->enableAuthorizer(); 575 576 // Spec 4.3.2.1+2: Open a transaction to the database, jumping to the error callback if that fails 577 if (!m_sqliteTransaction->inProgress()) { 578 ASSERT(!m_database->sqliteDatabase().transactionInProgress()); 579 m_database->reportStartTransactionResult(2, SQLError::DATABASE_ERR, m_database->sqliteDatabase().lastError()); 580 m_transactionError = SQLErrorData::create(SQLError::DATABASE_ERR, "unable to begin transaction", 581 m_database->sqliteDatabase().lastError(), m_database->sqliteDatabase().lastErrorMsg()); 582 m_sqliteTransaction.clear(); 583 return nextStateForTransactionError(); 584 } 585 586 // Note: We intentionally retrieve the actual version even with an empty expected version. 587 // In multi-process browsers, we take this opportinutiy to update the cached value for 588 // the actual version. In single-process browsers, this is just a map lookup. 589 String actualVersion; 590 if (!m_database->getActualVersionForTransaction(actualVersion)) { 591 m_database->reportStartTransactionResult(3, SQLError::DATABASE_ERR, m_database->sqliteDatabase().lastError()); 592 m_transactionError = SQLErrorData::create(SQLError::DATABASE_ERR, "unable to read version", 593 m_database->sqliteDatabase().lastError(), m_database->sqliteDatabase().lastErrorMsg()); 594 m_database->disableAuthorizer(); 595 m_sqliteTransaction.clear(); 596 m_database->enableAuthorizer(); 597 return nextStateForTransactionError(); 598 } 599 m_hasVersionMismatch = !m_database->expectedVersion().isEmpty() && (m_database->expectedVersion() != actualVersion); 600 601 // Spec 4.3.2.3: Perform preflight steps, jumping to the error callback if they fail 602 if (m_wrapper && !m_wrapper->performPreflight(this)) { 603 m_database->disableAuthorizer(); 604 m_sqliteTransaction.clear(); 605 m_database->enableAuthorizer(); 606 if (m_wrapper->sqlError()) { 607 m_transactionError = SQLErrorData::create(*m_wrapper->sqlError()); 608 } else { 609 m_database->reportStartTransactionResult(4, SQLError::UNKNOWN_ERR, 0); 610 m_transactionError = SQLErrorData::create(SQLError::UNKNOWN_ERR, "unknown error occurred during transaction preflight"); 611 } 612 return nextStateForTransactionError(); 613 } 614 615 // Spec 4.3.2.4: Invoke the transaction callback with the new SQLTransaction object 616 if (m_hasCallback) 617 return SQLTransactionState::DeliverTransactionCallback; 618 619 // If we have no callback to make, skip pass to the state after: 620 return SQLTransactionState::RunStatements; 621} 622 623SQLTransactionState SQLTransactionBackend::runStatements() 624{ 625 ASSERT(m_lockAcquired); 626 SQLTransactionState nextState; 627 628 // If there is a series of statements queued up that are all successful and have no associated 629 // SQLStatementCallback objects, then we can burn through the queue 630 do { 631 if (m_shouldRetryCurrentStatement && !m_sqliteTransaction->wasRolledBackBySqlite()) { 632 m_shouldRetryCurrentStatement = false; 633 // FIXME - Another place that needs fixing up after <rdar://problem/5628468> is addressed. 634 // See ::openTransactionAndPreflight() for discussion 635 636 // Reset the maximum size here, as it was increased to allow us to retry this statement. 637 // m_shouldRetryCurrentStatement is set to true only when a statement exceeds 638 // the quota, which can happen only in a read-write transaction. Therefore, there 639 // is no need to check here if the transaction is read-write. 640 m_database->sqliteDatabase().setMaximumSize(m_database->maximumSize()); 641 } else { 642 // If the current statement has already been run, failed due to quota constraints, and we're not retrying it, 643 // that means it ended in an error. Handle it now 644 if (m_currentStatementBackend && m_currentStatementBackend->lastExecutionFailedDueToQuota()) { 645 return nextStateForCurrentStatementError(); 646 } 647 648 // Otherwise, advance to the next statement 649 getNextStatement(); 650 } 651 nextState = runCurrentStatementAndGetNextState(); 652 } while (nextState == SQLTransactionState::RunStatements); 653 654 return nextState; 655} 656 657void SQLTransactionBackend::getNextStatement() 658{ 659 m_currentStatementBackend = nullptr; 660 661 MutexLocker locker(m_statementMutex); 662 if (!m_statementQueue.isEmpty()) 663 m_currentStatementBackend = m_statementQueue.takeFirst(); 664} 665 666SQLTransactionState SQLTransactionBackend::runCurrentStatementAndGetNextState() 667{ 668 if (!m_currentStatementBackend) { 669 // No more statements to run. So move on to the next state. 670 return SQLTransactionState::PostflightAndCommit; 671 } 672 673 m_database->resetAuthorizer(); 674 675 if (m_hasVersionMismatch) 676 m_currentStatementBackend->setVersionMismatchedError(m_database.get()); 677 678 if (m_currentStatementBackend->execute(m_database.get())) { 679 if (m_database->lastActionChangedDatabase()) { 680 // Flag this transaction as having changed the database for later delegate notification 681 m_modifiedDatabase = true; 682 } 683 684 if (m_currentStatementBackend->hasStatementCallback()) { 685 return SQLTransactionState::DeliverStatementCallback; 686 } 687 688 // If we get here, then the statement doesn't have a callback to invoke. 689 // We can move on to the next statement. Hence, stay in this state. 690 return SQLTransactionState::RunStatements; 691 } 692 693 if (m_currentStatementBackend->lastExecutionFailedDueToQuota()) { 694 return SQLTransactionState::DeliverQuotaIncreaseCallback; 695 } 696 697 return nextStateForCurrentStatementError(); 698} 699 700SQLTransactionState SQLTransactionBackend::nextStateForCurrentStatementError() 701{ 702 // Spec 4.3.2.6.6: error - Call the statement's error callback, but if there was no error callback, 703 // or the transaction was rolled back, jump to the transaction error callback 704 if (m_currentStatementBackend->hasStatementErrorCallback() && !m_sqliteTransaction->wasRolledBackBySqlite()) 705 return SQLTransactionState::DeliverStatementCallback; 706 707 if (m_currentStatementBackend->sqlError()) { 708 m_transactionError = SQLErrorData::create(*m_currentStatementBackend->sqlError()); 709 } else { 710 m_database->reportCommitTransactionResult(1, SQLError::DATABASE_ERR, 0); 711 m_transactionError = SQLErrorData::create(SQLError::DATABASE_ERR, "the statement failed to execute"); 712 } 713 return nextStateForTransactionError(); 714} 715 716SQLTransactionState SQLTransactionBackend::postflightAndCommit() 717{ 718 ASSERT(m_lockAcquired); 719 720 // Spec 4.3.2.7: Perform postflight steps, jumping to the error callback if they fail. 721 if (m_wrapper && !m_wrapper->performPostflight(this)) { 722 if (m_wrapper->sqlError()) { 723 m_transactionError = SQLErrorData::create(*m_wrapper->sqlError()); 724 } else { 725 m_database->reportCommitTransactionResult(3, SQLError::UNKNOWN_ERR, 0); 726 m_transactionError = SQLErrorData::create(SQLError::UNKNOWN_ERR, "unknown error occurred during transaction postflight"); 727 } 728 return nextStateForTransactionError(); 729 } 730 731 // Spec 4.3.2.7: Commit the transaction, jumping to the error callback if that fails. 732 ASSERT(m_sqliteTransaction); 733 734 m_database->disableAuthorizer(); 735 m_sqliteTransaction->commit(); 736 m_database->enableAuthorizer(); 737 738 // If the commit failed, the transaction will still be marked as "in progress" 739 if (m_sqliteTransaction->inProgress()) { 740 if (m_wrapper) 741 m_wrapper->handleCommitFailedAfterPostflight(this); 742 m_database->reportCommitTransactionResult(4, SQLError::DATABASE_ERR, m_database->sqliteDatabase().lastError()); 743 m_transactionError = SQLErrorData::create(SQLError::DATABASE_ERR, "unable to commit transaction", 744 m_database->sqliteDatabase().lastError(), m_database->sqliteDatabase().lastErrorMsg()); 745 return nextStateForTransactionError(); 746 } 747 748 m_database->reportCommitTransactionResult(0, -1, 0); // OK 749 750 // Vacuum the database if anything was deleted. 751 if (m_database->hadDeletes()) 752 m_database->incrementalVacuumIfNeeded(); 753 754 // The commit was successful. If the transaction modified this database, notify the delegates. 755 if (m_modifiedDatabase) 756 m_database->transactionClient()->didCommitWriteTransaction(database()); 757 758 // Spec 4.3.2.8: Deliver success callback, if there is one. 759 return SQLTransactionState::DeliverSuccessCallback; 760} 761 762SQLTransactionState SQLTransactionBackend::cleanupAndTerminate() 763{ 764 ASSERT(m_lockAcquired); 765 766 // Spec 4.3.2.9: End transaction steps. There is no next step. 767 WTF_LOG(StorageAPI, "Transaction %p is complete\n", this); 768 ASSERT(!m_database->sqliteDatabase().transactionInProgress()); 769 770 // Phase 5 cleanup. See comment on the SQLTransaction life-cycle above. 771 doCleanup(); 772 m_database->inProgressTransactionCompleted(); 773 return SQLTransactionState::End; 774} 775 776SQLTransactionState SQLTransactionBackend::nextStateForTransactionError() 777{ 778 ASSERT(m_transactionError); 779 if (m_hasErrorCallback) 780 return SQLTransactionState::DeliverTransactionErrorCallback; 781 782 // No error callback, so fast-forward to the next state and rollback the 783 // transaction. 784 return SQLTransactionState::CleanupAfterTransactionErrorCallback; 785} 786 787SQLTransactionState SQLTransactionBackend::cleanupAfterTransactionErrorCallback() 788{ 789 ASSERT(m_lockAcquired); 790 791 WTF_LOG(StorageAPI, "Transaction %p is complete with an error\n", this); 792 m_database->disableAuthorizer(); 793 if (m_sqliteTransaction) { 794 // Spec 4.3.2.10: Rollback the transaction. 795 m_sqliteTransaction->rollback(); 796 797 ASSERT(!m_database->sqliteDatabase().transactionInProgress()); 798 m_sqliteTransaction.clear(); 799 } 800 m_database->enableAuthorizer(); 801 802 ASSERT(!m_database->sqliteDatabase().transactionInProgress()); 803 804 return SQLTransactionState::CleanupAndTerminate; 805} 806 807// requestTransitToState() can be called from the frontend. Hence, it should 808// NOT be modifying SQLTransactionBackend in general. The only safe field to 809// modify is m_requestedState which is meant for this purpose. 810void SQLTransactionBackend::requestTransitToState(SQLTransactionState nextState) 811{ 812 WTF_LOG(StorageAPI, "Scheduling %s for transaction %p\n", nameForSQLTransactionState(nextState), this); 813 m_requestedState = nextState; 814 ASSERT(m_requestedState != SQLTransactionState::End); 815 m_database->scheduleTransactionStep(this); 816} 817 818// This state function is used as a stub function to plug unimplemented states 819// in the state dispatch table. They are unimplemented because they should 820// never be reached in the course of correct execution. 821SQLTransactionState SQLTransactionBackend::unreachableState() 822{ 823 ASSERT_NOT_REACHED(); 824 return SQLTransactionState::End; 825} 826 827SQLTransactionState SQLTransactionBackend::sendToFrontendState() 828{ 829 ASSERT(m_nextState != SQLTransactionState::Idle); 830 m_frontend->requestTransitToState(m_nextState); 831 return SQLTransactionState::Idle; 832} 833 834} // namespace blink 835