15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/* 25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright (C) 2009 Google Inc. All rights reserved. 3926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * Copyright (C) 2013 Apple Inc. All rights reserved. 45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without 65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions are 75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * met: 85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * * Redistributions of source code must retain the above copyright 105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * notice, this list of conditions and the following disclaimer. 115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * * Redistributions in binary form must reproduce the above 125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * copyright notice, this list of conditions and the following disclaimer 135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * in the documentation and/or other materials provided with the 145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * distribution. 155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * * Neither the name of Google Inc. nor the names of its 165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * contributors may be used to endorse or promote products derived from 175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * this software without specific prior written permission. 185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 305c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */ 315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 325c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h" 3353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "modules/webdatabase/SQLTransactionCoordinator.h" 345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 357242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci#include "modules/webdatabase/Database.h" 3653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "modules/webdatabase/SQLTransactionBackend.h" 375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 38c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)namespace blink { 395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 40926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)static String getDatabaseIdentifier(SQLTransactionBackend* transaction) 415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 427242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci Database* database = transaction->database(); 435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(database); 445267f701546148b83dfbe1d151cb184385bb5c22Torne (Richard Coles) return database->stringIdentifier(); 45926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)} 46926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 47926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)SQLTransactionCoordinator::SQLTransactionCoordinator() 48926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) : m_isShuttingDown(false) 49926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles){ 505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 5243e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)void SQLTransactionCoordinator::trace(Visitor* visitor) 5343e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles){ 54c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)#if ENABLE(OILPAN) 5543e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles) visitor->trace(m_coordinationInfoMap); 56c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)#endif 5743e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)} 5843e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles) 595c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SQLTransactionCoordinator::processPendingTransactions(CoordinationInfo& info) 605c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (info.activeWriteTransaction || info.pendingTransactions.isEmpty()) 625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 6443e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles) RefPtrWillBeRawPtr<SQLTransactionBackend> firstPendingTransaction = info.pendingTransactions.first(); 655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (firstPendingTransaction->isReadOnly()) { 665c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) do { 675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) firstPendingTransaction = info.pendingTransactions.takeFirst(); 685c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) info.activeReadTransactions.add(firstPendingTransaction); 695c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) firstPendingTransaction->lockAcquired(); 705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } while (!info.pendingTransactions.isEmpty() && info.pendingTransactions.first()->isReadOnly()); 715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else if (info.activeReadTransactions.isEmpty()) { 725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) info.pendingTransactions.removeFirst(); 735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) info.activeWriteTransaction = firstPendingTransaction; 745c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) firstPendingTransaction->lockAcquired(); 755c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 765c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 78926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)void SQLTransactionCoordinator::acquireLock(SQLTransactionBackend* transaction) 795c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 80926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) ASSERT(!m_isShuttingDown); 81926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 825c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) String dbIdentifier = getDatabaseIdentifier(transaction); 835c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 8443e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles) CoordinationInfoHeapMap::iterator coordinationInfoIterator = m_coordinationInfoMap.find(dbIdentifier); 855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (coordinationInfoIterator == m_coordinationInfoMap.end()) { 865c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // No pending transactions for this DB 8709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) CoordinationInfo& info = m_coordinationInfoMap.add(dbIdentifier, CoordinationInfo()).storedValue->value; 8809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) info.pendingTransactions.append(transaction); 8909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) processPendingTransactions(info); 9009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) } else { 9109380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) CoordinationInfo& info = coordinationInfoIterator->value; 9209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) info.pendingTransactions.append(transaction); 9309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) processPendingTransactions(info); 945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 98926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)void SQLTransactionCoordinator::releaseLock(SQLTransactionBackend* transaction) 995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 100926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) if (m_isShuttingDown) 1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) return; 1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1035c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) String dbIdentifier = getDatabaseIdentifier(transaction); 1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 10543e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles) CoordinationInfoHeapMap::iterator coordinationInfoIterator = m_coordinationInfoMap.find(dbIdentifier); 10651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) ASSERT_WITH_SECURITY_IMPLICATION(coordinationInfoIterator != m_coordinationInfoMap.end()); 1075c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) CoordinationInfo& info = coordinationInfoIterator->value; 1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1095c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (transaction->isReadOnly()) { 1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(info.activeReadTransactions.contains(transaction)); 1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) info.activeReadTransactions.remove(transaction); 1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } else { 1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(info.activeWriteTransaction == transaction); 114d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) info.activeWriteTransaction = nullptr; 1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) processPendingTransactions(info); 1185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void SQLTransactionCoordinator::shutdown() 1215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 122926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // Prevent releaseLock() from accessing / changing the coordinationInfo 123926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // while we're shutting down. 124926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) m_isShuttingDown = true; 125926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 1265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Notify all transactions in progress that the database thread is shutting down 12743e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles) for (CoordinationInfoHeapMap::iterator coordinationInfoIterator = m_coordinationInfoMap.begin(); 1285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) coordinationInfoIterator != m_coordinationInfoMap.end(); ++coordinationInfoIterator) { 1295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) CoordinationInfo& info = coordinationInfoIterator->value; 130926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 131926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // Clean up transactions that have reached "lockAcquired": 132926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // Transaction phase 4 cleanup. See comment on "What happens if a 133926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // transaction is interrupted?" at the top of SQLTransactionBackend.cpp. 1345c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (info.activeWriteTransaction) 1355c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) info.activeWriteTransaction->notifyDatabaseThreadIsShuttingDown(); 13643e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles) for (WillBeHeapHashSet<RefPtrWillBeMember<SQLTransactionBackend> >::iterator activeReadTransactionsIterator = 1375c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) info.activeReadTransactions.begin(); 1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) activeReadTransactionsIterator != info.activeReadTransactions.end(); 1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ++activeReadTransactionsIterator) { 1405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) (*activeReadTransactionsIterator)->notifyDatabaseThreadIsShuttingDown(); 1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 142926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) 143926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // Clean up transactions that have NOT reached "lockAcquired": 144926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // Transaction phase 3 cleanup. See comment on "What happens if a 145926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) // transaction is interrupted?" at the top of SQLTransactionBackend.cpp. 146926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) while (!info.pendingTransactions.isEmpty()) { 1477242dc3dbeb210b5e876a3c42d1ec1a667fc621aPrimiano Tucci RefPtrWillBeRawPtr<SQLTransactionBackend> transaction = info.pendingTransactions.takeFirst(); 148926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) transaction->notifyDatabaseThreadIsShuttingDown(); 149926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) } 1505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Clean up all pending transactions for all databases 1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_coordinationInfoMap.clear(); 1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 156c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)} // namespace blink 157