15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/* 2926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles) * Copyright (C) 2007, 2008, 2013 Apple Inc. All rights reserved. 35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Redistribution and use in source and binary forms, with or without 55c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * modification, are permitted provided that the following conditions 65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * are met: 75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 1. Redistributions of source code must retain the above copyright 95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * notice, this list of conditions and the following disclaimer. 105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 2. Redistributions in binary form must reproduce the above copyright 115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * notice, this list of conditions and the following disclaimer in the 125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * documentation and/or other materials provided with the distribution. 135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of 145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * its contributors may be used to endorse or promote products derived 155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * from this software without specific prior written permission. 165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * 175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 255c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 265c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 275c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */ 285c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 295c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "config.h" 3053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "modules/webdatabase/DatabaseThread.h" 315c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 3253e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "modules/webdatabase/Database.h" 3353e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "modules/webdatabase/DatabaseTask.h" 3453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "modules/webdatabase/SQLTransactionClient.h" 3553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#include "modules/webdatabase/SQLTransactionCoordinator.h" 36a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "platform/Logging.h" 37a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#include "platform/heap/glue/MessageLoopInterruptor.h" 38a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch#include "platform/heap/glue/PendingGCRunner.h" 39a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)#include "public/platform/Platform.h" 405c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)namespace WebCore { 425c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)DatabaseThread::DatabaseThread() 44a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) : m_transactionClient(adoptPtr(new SQLTransactionClient())) 4543e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles) , m_transactionCoordinator(adoptPtrWillBeNoop(new SQLTransactionCoordinator())) 465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) , m_cleanupSync(0) 47a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) , m_terminationRequested(false) 485c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 505c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)DatabaseThread::~DatabaseThread() 525c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 53d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) ASSERT(m_openDatabaseSet.isEmpty()); 54d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) // Oilpan: The database thread must have finished its cleanup tasks before 55d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) // the following clear(). Otherwise, WebThread destructor blocks the caller 56d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) // thread, and causes a deadlock with ThreadState cleanup. 57d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) // DatabaseContext::stop() asks the database thread to close all of 58d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) // databases, and wait until GC heap cleanup of the database thread. So we 59d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) // can safely destruct WebThread here. 60a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) m_thread.clear(); 615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 6343e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)void DatabaseThread::trace(Visitor* visitor) 6443e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles){ 6543e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles) visitor->trace(m_openDatabaseSet); 6643e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles) visitor->trace(m_transactionCoordinator); 6743e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles)} 6843e7502580f146aa5b3db8267ba6dbb5c733a489Torne (Richard Coles) 69a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)void DatabaseThread::start() 705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 71a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) if (m_thread) 72a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) return; 73a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) m_thread = adoptPtr(blink::Platform::current()->createThread("WebCore: Database")); 74d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) m_thread->postTask(new Task(WTF::bind(&DatabaseThread::setupDatabaseThread, this))); 75d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)} 76d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 77d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)void DatabaseThread::setupDatabaseThread() 78d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){ 79d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) m_pendingGCRunner = adoptPtr(new PendingGCRunner); 80d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) m_messageLoopInterruptor = adoptPtr(new MessageLoopInterruptor(m_thread.get())); 81d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) m_thread->addTaskObserver(m_pendingGCRunner.get()); 82d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) ThreadState::attach(); 83d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) ThreadState::current()->addInterruptor(m_messageLoopInterruptor.get()); 845c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 86a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochvoid DatabaseThread::requestTermination(TaskSynchronizer *cleanupSync) 875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 8809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) MutexLocker lock(m_terminationRequestedMutex); 89a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) ASSERT(!m_terminationRequested); 90a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) m_terminationRequested = true; 915c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_cleanupSync = cleanupSync; 92a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF_LOG(StorageAPI, "DatabaseThread %p was asked to terminate\n", this); 93a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) m_thread->postTask(new Task(WTF::bind(&DatabaseThread::cleanupDatabaseThread, this))); 945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 96a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdochbool DatabaseThread::terminationRequested(TaskSynchronizer* taskSynchronizer) const 975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#ifndef NDEBUG 995c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (taskSynchronizer) 1005c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) taskSynchronizer->setHasCheckedForTermination(); 1015c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#endif 1025c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 10309380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) MutexLocker lock(m_terminationRequestedMutex); 104a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) return m_terminationRequested; 1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1065c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 107a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)void DatabaseThread::cleanupDatabaseThread() 1085c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 109a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) WTF_LOG(StorageAPI, "Cleaning up DatabaseThread %p", this); 1105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Clean up the list of all pending transactions on this database thread 1125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_transactionCoordinator->shutdown(); 1135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // Close the databases that we ran transactions on. This ensures that if any transactions are still open, they are rolled back and we don't leave the database in an 1155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // inconsistent or locked state. 1165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) if (m_openDatabaseSet.size() > 0) { 1175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) // As the call to close will modify the original set, we must take a copy to iterate over. 118d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) WillBeHeapHashSet<RefPtrWillBeMember<DatabaseBackend> > openSetCopy; 1195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) openSetCopy.swap(m_openDatabaseSet); 120d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) WillBeHeapHashSet<RefPtrWillBeMember<DatabaseBackend> >::iterator end = openSetCopy.end(); 121d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) for (WillBeHeapHashSet<RefPtrWillBeMember<DatabaseBackend> >::iterator it = openSetCopy.begin(); it != end; ++it) 122d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) (*it)->close(); 1235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) } 1245c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 125d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) m_thread->postTask(new Task(WTF::bind(&DatabaseThread::cleanupDatabaseThreadCompleted, this))); 126d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)} 127d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 128d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles)void DatabaseThread::cleanupDatabaseThreadCompleted() 129d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles){ 130d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) ThreadState::current()->removeInterruptor(m_messageLoopInterruptor.get()); 131d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) ThreadState::detach(); 132d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) // We need to unregister PendingGCRunner before finising this task to avoid 133d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) // PendingGCRunner::didProcessTask accesses dead ThreadState. 134d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) m_thread->removeTaskObserver(m_pendingGCRunner.get()); 135d5428f32f5d1719f774f62e19147104ca245a3abTorne (Richard Coles) 136a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) if (m_cleanupSync) // Someone wanted to know when we were done cleaning up. 137a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) m_cleanupSync->taskCompleted(); 1385c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1395c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 140926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)void DatabaseThread::recordDatabaseOpen(DatabaseBackend* database) 1415c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 14251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) ASSERT(isDatabaseThread()); 1435c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(database); 1445c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(!m_openDatabaseSet.contains(database)); 1455c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_openDatabaseSet.add(database); 1465c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1475c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 148926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)void DatabaseThread::recordDatabaseClosed(DatabaseBackend* database) 1495c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 15051b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) ASSERT(isDatabaseThread()); 1515c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(database); 152a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) ASSERT(m_terminationRequested || m_openDatabaseSet.contains(database)); 1535c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) m_openDatabaseSet.remove(database); 1545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1555c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 15651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)bool DatabaseThread::isDatabaseOpen(DatabaseBackend* database) 1575c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 15851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) ASSERT(isDatabaseThread()); 15951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles) ASSERT(database); 16009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles) MutexLocker lock(m_terminationRequestedMutex); 161a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) return !m_terminationRequested && m_openDatabaseSet.contains(database); 1625c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1635c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 16451b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)void DatabaseThread::scheduleTask(PassOwnPtr<DatabaseTask> task) 1655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles){ 166a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) ASSERT(m_thread); 1675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) ASSERT(!task->hasSynchronizer() || task->hasCheckedForTermination()); 168a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) // WebThread takes ownership of the task. 169a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles) m_thread->postTask(task.leakPtr()); 1705c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} 1715c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) 1725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)} // namespace WebCore 173