1231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block/* 2231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * Copyright (C) 2009 Google Inc. All rights reserved. 3231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * 4231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * Redistribution and use in source and binary forms, with or without 5231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * modification, are permitted provided that the following conditions are 6231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * met: 7231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * 8231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * * Redistributions of source code must retain the above copyright 9231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * notice, this list of conditions and the following disclaimer. 10231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * * Redistributions in binary form must reproduce the above 11231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * copyright notice, this list of conditions and the following disclaimer 12231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * in the documentation and/or other materials provided with the 13231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * distribution. 14231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * * Neither the name of Google Inc. nor the names of its 15231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * contributors may be used to endorse or promote products derived from 16231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * this software without specific prior written permission. 17231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * 18231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block */ 30231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 31231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include "config.h" 32231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include "SQLTransactionCoordinator.h" 33231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 34d0825bca7fe65beaee391d30da42e937db621564Steve Block#if ENABLE(DATABASE) 35d0825bca7fe65beaee391d30da42e937db621564Steve Block 36231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include "Database.h" 37231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include "SQLTransaction.h" 38231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include <wtf/Deque.h> 39231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include <wtf/HashMap.h> 40231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include <wtf/HashSet.h> 41231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include <wtf/RefPtr.h> 42231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 43231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blocknamespace WebCore { 44231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 45231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockstatic String getDatabaseIdentifier(SQLTransaction* transaction) 46231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{ 47231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block Database* database = transaction->database(); 48231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block ASSERT(database); 49231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return database->stringIdentifier(); 50231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block} 51231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 52231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockvoid SQLTransactionCoordinator::processPendingTransactions(CoordinationInfo& info) 53231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{ 54231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if (info.activeWriteTransaction || info.pendingTransactions.isEmpty()) 55231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return; 56231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 57231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block RefPtr<SQLTransaction> firstPendingTransaction = info.pendingTransactions.first(); 58231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if (firstPendingTransaction->isReadOnly()) { 59231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block do { 60545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch firstPendingTransaction = info.pendingTransactions.takeFirst(); 61231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block info.activeReadTransactions.add(firstPendingTransaction); 62231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block firstPendingTransaction->lockAcquired(); 63231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block } while (!info.pendingTransactions.isEmpty() && info.pendingTransactions.first()->isReadOnly()); 64231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block } else if (info.activeReadTransactions.isEmpty()) { 65231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block info.pendingTransactions.removeFirst(); 66231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block info.activeWriteTransaction = firstPendingTransaction; 67231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block firstPendingTransaction->lockAcquired(); 68231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block } 69231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block} 70231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 71231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockvoid SQLTransactionCoordinator::acquireLock(SQLTransaction* transaction) 72231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{ 73231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block String dbIdentifier = getDatabaseIdentifier(transaction); 74231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 75231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block CoordinationInfoMap::iterator coordinationInfoIterator = m_coordinationInfoMap.find(dbIdentifier); 76231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if (coordinationInfoIterator == m_coordinationInfoMap.end()) { 77231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block // No pending transactions for this DB 78231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block coordinationInfoIterator = m_coordinationInfoMap.add(dbIdentifier, CoordinationInfo()).first; 79231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block } 80231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 81231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block CoordinationInfo& info = coordinationInfoIterator->second; 82231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block info.pendingTransactions.append(transaction); 83231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block processPendingTransactions(info); 84231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block} 85231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 86231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockvoid SQLTransactionCoordinator::releaseLock(SQLTransaction* transaction) 87231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{ 88231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if (m_coordinationInfoMap.isEmpty()) 89231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block return; 90231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 91231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block String dbIdentifier = getDatabaseIdentifier(transaction); 92231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 93231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block CoordinationInfoMap::iterator coordinationInfoIterator = m_coordinationInfoMap.find(dbIdentifier); 94231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block ASSERT(coordinationInfoIterator != m_coordinationInfoMap.end()); 95231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block CoordinationInfo& info = coordinationInfoIterator->second; 96231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 97231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block if (transaction->isReadOnly()) { 98231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block ASSERT(info.activeReadTransactions.contains(transaction)); 99231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block info.activeReadTransactions.remove(transaction); 100231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block } else { 101231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block ASSERT(info.activeWriteTransaction == transaction); 102231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block info.activeWriteTransaction = 0; 103231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block } 104231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 105231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block processPendingTransactions(info); 106231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block} 107231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 108231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockvoid SQLTransactionCoordinator::shutdown() 109231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{ 1105e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block // Notify all transactions in progress that the database thread is shutting down 1115e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block for (CoordinationInfoMap::iterator coordinationInfoIterator = m_coordinationInfoMap.begin(); 1125e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block coordinationInfoIterator != m_coordinationInfoMap.end(); ++coordinationInfoIterator) { 1135e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block CoordinationInfo& info = coordinationInfoIterator->second; 1145e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block if (info.activeWriteTransaction) 1155e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block info.activeWriteTransaction->notifyDatabaseThreadIsShuttingDown(); 1165e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block for (HashSet<RefPtr<SQLTransaction> >::iterator activeReadTransactionsIterator = 1175e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block info.activeReadTransactions.begin(); 1185e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block activeReadTransactionsIterator != info.activeReadTransactions.end(); 1195e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block ++activeReadTransactionsIterator) { 1205e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block (*activeReadTransactionsIterator)->notifyDatabaseThreadIsShuttingDown(); 1215e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block } 1225e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block } 1235e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block 124231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block // Clean up all pending transactions for all databases 125231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block m_coordinationInfoMap.clear(); 126231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block} 127231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block 128d0825bca7fe65beaee391d30da42e937db621564Steve Block} // namespace WebCore 129d0825bca7fe65beaee391d30da42e937db621564Steve Block 130d0825bca7fe65beaee391d30da42e937db621564Steve Block#endif // ENABLE(DATABASE) 131