Changeset 47170 in webkit
- Timestamp:
- Aug 12, 2009 5:52:54 PM (15 years ago)
- Location:
- trunk
- Files:
-
- 4 added
- 12 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/LayoutTests/ChangeLog
r47169 r47170 1 2009-08-12 Dumitru Daniliuc <dumi@chromium.org> 2 3 Reviewed by Eric Seidel. 4 5 Regression test. Tests that two transactions that run on two 6 different handles for the same DB do not cause a deadlock. 7 8 https://bugs.webkit.org/show_bug?id=27966 9 10 * storage/multiple-transactions-on-different-handles-expected.txt: Added. 11 * storage/multiple-transactions-on-different-handles.html: Added. 12 1 13 2009-08-12 Eric Seidel <eric@webkit.org> 2 14 -
trunk/WebCore/ChangeLog
r47165 r47170 1 2009-08-12 Dumitru Daniliuc <dumi@chromium.org> 2 3 Reviewed by Eric Seidel. 4 5 Fixing a deadlock caused by two transactions that run on two 6 different database handles for the same DB. Adding a per-DB thread 7 transaction coordinator that allows the DB thread to run only one 8 transaction per DB file at any given time. 9 10 Adding a regression test for this bug. 11 12 Test: storage/multiple-transactions-on-different-handles.html 13 14 https://bugs.webkit.org/show_bug.cgi?id=27996 15 16 * GNUmakefile.am: 17 * WebCore.gypi: 18 * WebCore.vcproj/WebCore.vcproj: 19 * WebCore.xcodeproj/project.pbxproj: 20 * storage/Database.cpp: 21 (WebCore::Database::transactionCoordinator): 22 * storage/Database.h: 23 * storage/DatabaseThread.cpp: 24 (WebCore::DatabaseThread::DatabaseThread): 25 * storage/DatabaseThread.h: 26 (WebCore::DatabaseThread::transactionCoordinator): 27 * storage/SQLTransaction.cpp: 28 (WebCore::SQLTransaction::SQLTransaction): 29 (WebCore::SQLTransaction::debugStepName): 30 (WebCore::SQLTransaction::performNextStep): 31 (WebCore::SQLTransaction::aquireLock): 32 (WebCore::SQLTransaction::lockAquired): 33 (WebCore::SQLTransaction::cleanupAfterSuccessCallback): 34 (WebCore::SQLTransaction::cleanupAfterTransactionErrorCallback): 35 * storage/SQLTransaction.h: 36 * storage/SQLTransactionCoordinator.cpp: Added. 37 * storage/SQLTransactionCoordinator.h: Added. 38 1 39 2009-08-12 Darin Adler <darin@apple.com> 2 40 -
trunk/WebCore/GNUmakefile.am
r47165 r47170 2117 2117 WebCore/storage/SQLTransaction.h \ 2118 2118 WebCore/storage/SQLTransactionCallback.h \ 2119 WebCore/storage/SQLTransactionCoordinator.h \ 2120 WebCore/storage/SQLTransactionCoordinator.cpp \ 2119 2121 WebCore/storage/SQLTransactionErrorCallback.h 2120 2122 -
trunk/WebCore/WebCore.gypi
r47165 r47170 2963 2963 'storage/SQLTransaction.h', 2964 2964 'storage/SQLTransactionCallback.h', 2965 'storage/SQLTransactionCoordinator.h', 2966 'storage/SQLTransactionCoordinator.cpp', 2965 2967 'storage/SQLTransactionErrorCallback.h', 2966 2968 'storage/Storage.cpp', -
trunk/WebCore/WebCore.vcproj/WebCore.vcproj
r47165 r47170 30737 30737 </File> 30738 30738 <File 30739 RelativePath="..\storage\SQLTransactionCoordinator.h" 30740 > 30741 </File> 30742 <File 30743 RelativePath="..\storage\SQLTransactionCoordinator.cpp" 30744 > 30745 </File> 30746 <File 30739 30747 RelativePath="..\storage\SQLTransactionErrorCallback.h" 30740 30748 > -
trunk/WebCore/WebCore.xcodeproj/project.pbxproj
r47165 r47170 3863 3863 B5A684220FFABE9800D24689 /* SQLiteFileSystem.h in Headers */ = {isa = PBXBuildFile; fileRef = B5A684210FFABE9800D24689 /* SQLiteFileSystem.h */; }; 3864 3864 B5A684240FFABEAA00D24689 /* SQLiteFileSystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B5A684230FFABEAA00D24689 /* SQLiteFileSystem.cpp */; }; 3865 B5C1123B102B6C4600096578 /* SQLTransactionCoordinator.cpp in Sources */ = {isa = PBXBuildFile; fileRef = B5C11239102B6C4600096578 /* SQLTransactionCoordinator.cpp */; }; 3866 B5C1123C102B6C4600096578 /* SQLTransactionCoordinator.h in Headers */ = {isa = PBXBuildFile; fileRef = B5C1123A102B6C4600096578 /* SQLTransactionCoordinator.h */; }; 3865 3867 BC00F0040E0A185500FD04E3 /* DOMFile.h in Headers */ = {isa = PBXBuildFile; fileRef = BC00EFFE0E0A185500FD04E3 /* DOMFile.h */; }; 3866 3868 BC00F0050E0A185500FD04E3 /* DOMFile.mm in Sources */ = {isa = PBXBuildFile; fileRef = BC00EFFF0E0A185500FD04E3 /* DOMFile.mm */; }; … … 8755 8757 B5A684210FFABE9800D24689 /* SQLiteFileSystem.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SQLiteFileSystem.h; path = sql/SQLiteFileSystem.h; sourceTree = "<group>"; }; 8756 8758 B5A684230FFABEAA00D24689 /* SQLiteFileSystem.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SQLiteFileSystem.cpp; path = sql/SQLiteFileSystem.cpp; sourceTree = "<group>"; }; 8759 B5C11239102B6C4600096578 /* SQLTransactionCoordinator.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = SQLTransactionCoordinator.cpp; sourceTree = "<group>"; }; 8760 B5C1123A102B6C4600096578 /* SQLTransactionCoordinator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SQLTransactionCoordinator.h; sourceTree = "<group>"; }; 8757 8761 BC00EFFE0E0A185500FD04E3 /* DOMFile.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DOMFile.h; sourceTree = "<group>"; }; 8758 8762 BC00EFFF0E0A185500FD04E3 /* DOMFile.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = DOMFile.mm; sourceTree = "<group>"; }; … … 9840 9844 isa = PBXGroup; 9841 9845 children = ( 9846 B5C11239102B6C4600096578 /* SQLTransactionCoordinator.cpp */, 9847 B5C1123A102B6C4600096578 /* SQLTransactionCoordinator.h */, 9842 9848 514185ED0CD65F0400763C99 /* ChangeVersionWrapper.cpp */, 9843 9849 514185EC0CD65F0400763C99 /* ChangeVersionWrapper.h */, … … 17253 17259 49484FCE102CF23C00187DD3 /* CanvasStyle.h in Headers */, 17254 17260 416E29A6102FA962007FC14E /* WorkerReportingProxy.h in Headers */, 17261 B5C1123C102B6C4600096578 /* SQLTransactionCoordinator.h in Headers */, 17255 17262 ); 17256 17263 runOnlyForDeploymentPostprocessing = 0; … … 19311 19318 9392262D1032107B006E7D5D /* JSHTMLCanvasElementCustom.cpp in Sources */, 19312 19319 9392262F10321084006E7D5D /* JSCSSRuleListCustom.cpp in Sources */, 19320 B5C1123B102B6C4600096578 /* SQLTransactionCoordinator.cpp in Sources */, 19313 19321 ); 19314 19322 runOnlyForDeploymentPostprocessing = 0; -
trunk/WebCore/storage/Database.cpp
r45594 r47170 51 51 #include "SQLiteStatement.h" 52 52 #include "SQLResultSet.h" 53 #include "SQLTransactionCoordinator.h" 53 54 #include <wtf/MainThread.h> 54 55 #endif … … 540 541 } 541 542 542 void Database::scheduleTransactionStep(SQLTransaction* transaction) 543 { 544 if (m_document->databaseThread()) { 545 RefPtr<DatabaseTransactionTask> task = DatabaseTransactionTask::create(transaction); 546 LOG(StorageAPI, "Scheduling DatabaseTransactionTask %p for the transaction step\n", task.get()); 543 void Database::scheduleTransactionStep(SQLTransaction* transaction, bool immediately) 544 { 545 if (!m_document->databaseThread()) 546 return; 547 548 RefPtr<DatabaseTransactionTask> task = DatabaseTransactionTask::create(transaction); 549 LOG(StorageAPI, "Scheduling DatabaseTransactionTask %p for the transaction step\n", task.get()); 550 if (immediately) 551 m_document->databaseThread()->scheduleImmediateTask(task.release()); 552 else 547 553 m_document->databaseThread()->scheduleTask(task.release()); 548 }549 554 } 550 555 … … 584 589 } 585 590 591 SQLTransactionCoordinator* Database::transactionCoordinator() const 592 { 593 return m_document->databaseThread()->transactionCoordinator(); 594 } 595 586 596 String Database::version() const 587 597 { -
trunk/WebCore/storage/Database.h
r45594 r47170 58 58 class SQLResultSet; 59 59 class SQLTransactionCallback; 60 class SQLTransactionCoordinator; 60 61 class SQLTransactionErrorCallback; 61 62 class SQLValue; … … 117 118 Vector<String> performGetTableNames(); 118 119 120 SQLTransactionCoordinator* transactionCoordinator() const; 121 119 122 private: 120 123 Database(Document* document, const String& name, const String& expectedVersion); … … 124 127 void scheduleTransaction(); 125 128 void scheduleTransactionCallback(SQLTransaction*); 126 void scheduleTransactionStep(SQLTransaction* transaction );129 void scheduleTransactionStep(SQLTransaction* transaction, bool immediately = false); 127 130 128 131 MessageQueue<RefPtr<SQLTransaction> > m_transactionQueue; -
trunk/WebCore/storage/DatabaseThread.cpp
r45594 r47170 36 36 #include "DatabaseTask.h" 37 37 #include "Logging.h" 38 #include "SQLTransactionCoordinator.h" 38 39 39 40 namespace WebCore { … … 41 42 DatabaseThread::DatabaseThread() 42 43 : m_threadID(0) 44 , m_transactionCoordinator(new SQLTransactionCoordinator()) 43 45 { 44 46 m_selfRef = this; … … 97 99 pool.cycle(); 98 100 } 101 102 // Clean up the list of all pending transactions on this database thread 103 m_transactionCoordinator->shutdown(); 99 104 100 105 LOG(StorageAPI, "About to detach thread %i and clear the ref to DatabaseThread %p, which currently has %i ref(s)", m_threadID, this, refCount()); -
trunk/WebCore/storage/DatabaseThread.h
r45594 r47170 34 34 #include <wtf/HashSet.h> 35 35 #include <wtf/MessageQueue.h> 36 #include <wtf/OwnPtr.h> 36 37 #include <wtf/PassRefPtr.h> 37 38 #include <wtf/RefPtr.h> … … 43 44 class DatabaseTask; 44 45 class Document; 46 class SQLTransactionCoordinator; 45 47 46 48 class DatabaseThread : public ThreadSafeShared<DatabaseThread> { … … 61 63 ThreadIdentifier getThreadID() { return m_threadID; } 62 64 65 SQLTransactionCoordinator* transactionCoordinator() { return m_transactionCoordinator.get(); } 66 63 67 private: 64 68 DatabaseThread(); … … 76 80 typedef HashSet<RefPtr<Database> > DatabaseSet; 77 81 DatabaseSet m_openDatabaseSet; 82 83 OwnPtr<SQLTransactionCoordinator> m_transactionCoordinator; 78 84 }; 79 85 -
trunk/WebCore/storage/SQLTransaction.cpp
r44274 r47170 51 51 #include "SQLStatementCallback.h" 52 52 #include "SQLStatementErrorCallback.h" 53 #include "SQLTransactionCoordinator.h" 53 54 #include "SQLValue.h" 54 55 … … 68 69 SQLTransaction::SQLTransaction(Database* db, PassRefPtr<SQLTransactionCallback> callback, PassRefPtr<SQLTransactionErrorCallback> errorCallback, PassRefPtr<VoidCallback> successCallback, 69 70 PassRefPtr<SQLTransactionWrapper> wrapper) 70 : m_nextStep(&SQLTransaction:: openTransactionAndPreflight)71 : m_nextStep(&SQLTransaction::acquireLock) 71 72 , m_executeSqlAllowed(false) 72 73 , m_database(db) … … 77 78 , m_shouldRetryCurrentStatement(false) 78 79 , m_modifiedDatabase(false) 80 , m_lockAcquired(false) 79 81 { 80 82 ASSERT(m_database); … … 117 119 const char* SQLTransaction::debugStepName(SQLTransaction::TransactionStepMethod step) 118 120 { 119 if (step == &SQLTransaction::openTransactionAndPreflight) 121 if (step == &SQLTransaction::acquireLock) 122 return "acquireLock"; 123 else if (step == &SQLTransaction::openTransactionAndPreflight) 120 124 return "openTransactionAndPreflight"; 121 125 else if (step == &SQLTransaction::runStatements) … … 158 162 m_sqliteTransaction.clear(); 159 163 } 164 165 if (m_lockAcquired) 166 m_database->transactionCoordinator()->releaseLock(this); 160 167 } 161 168 … … 165 172 LOG(StorageAPI, "Step %s\n", debugStepName(m_nextStep)); 166 173 167 ASSERT(m_nextStep == &SQLTransaction::openTransactionAndPreflight || 174 ASSERT(m_nextStep == &SQLTransaction::acquireLock || 175 m_nextStep == &SQLTransaction::openTransactionAndPreflight || 168 176 m_nextStep == &SQLTransaction::runStatements || 169 177 m_nextStep == &SQLTransaction::postflightAndCommit || … … 196 204 } 197 205 206 void SQLTransaction::acquireLock() 207 { 208 m_database->transactionCoordinator()->acquireLock(this); 209 } 210 211 void SQLTransaction::lockAcquired() 212 { 213 m_lockAcquired = true; 214 m_nextStep = &SQLTransaction::openTransactionAndPreflight; 215 LOG(StorageAPI, "Scheduling openTransactionAndPreflight immediately for transaction %p\n", this); 216 m_database->scheduleTransactionStep(this, true); 217 } 218 198 219 void SQLTransaction::openTransactionAndPreflight() 199 220 { 200 221 ASSERT(!m_database->m_sqliteDatabase.transactionInProgress()); 222 ASSERT(m_lockAcquired); 201 223 202 224 LOG(StorageAPI, "Opening and preflighting transaction %p", this); … … 274 296 void SQLTransaction::runStatements() 275 297 { 298 ASSERT(m_lockAcquired); 299 276 300 // If there is a series of statements queued up that are all successful and have no associated 277 301 // SQLStatementCallback objects, then we can burn through the queue … … 412 436 void SQLTransaction::postflightAndCommit() 413 437 { 438 ASSERT(m_lockAcquired); 439 414 440 // Transaction Step 7 - Peform postflight steps, jumping to the error callback if they fail 415 441 if (m_wrapper && !m_wrapper->performPostflight(this)) { … … 470 496 void SQLTransaction::cleanupAfterSuccessCallback() 471 497 { 498 ASSERT(m_lockAcquired); 499 472 500 // Transaction Step 11 - End transaction steps 473 501 // There is no next step … … 475 503 ASSERT(!m_database->m_sqliteDatabase.transactionInProgress()); 476 504 m_nextStep = 0; 505 506 // Release the lock on this database 507 m_database->transactionCoordinator()->releaseLock(this); 477 508 } 478 509 … … 517 548 void SQLTransaction::cleanupAfterTransactionErrorCallback() 518 549 { 550 ASSERT(m_lockAcquired); 551 519 552 m_database->m_databaseAuthorizer->disable(); 520 553 if (m_sqliteTransaction) { … … 541 574 m_callback = 0; 542 575 m_errorCallback = 0; 576 577 // Now release the lock on this database 578 m_database->transactionCoordinator()->releaseLock(this); 543 579 } 544 580 -
trunk/WebCore/storage/SQLTransaction.h
r44155 r47170 74 74 PassRefPtr<SQLStatementCallback> callback, PassRefPtr<SQLStatementErrorCallback> callbackError, ExceptionCode& e); 75 75 76 void lockAcquired(); 76 77 bool performNextStep(); 77 78 void performPendingCallback(); … … 89 90 void checkAndHandleClosedDatabase(); 90 91 92 void acquireLock(); 91 93 void openTransactionAndPreflight(); 92 94 void deliverTransactionCallback(); … … 121 123 bool m_shouldRetryCurrentStatement; 122 124 bool m_modifiedDatabase; 125 bool m_lockAcquired; 123 126 124 127 Mutex m_statementMutex;
Note: See TracChangeset
for help on using the changeset viewer.