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/DatabaseThread.h" 31 32 #include "modules/webdatabase/Database.h" 33 #include "modules/webdatabase/DatabaseTask.h" 34 #include "modules/webdatabase/SQLTransactionClient.h" 35 #include "modules/webdatabase/SQLTransactionCoordinator.h" 36 #include "platform/Logging.h" 37 #include "public/platform/Platform.h" 38 #include "wtf/AutodrainedPool.h" 39 40 namespace WebCore { 41 42 DatabaseThread::DatabaseThread() 43 : m_transactionClient(adoptPtr(new SQLTransactionClient())) 44 , m_transactionCoordinator(adoptPtr(new SQLTransactionCoordinator())) 45 , m_cleanupSync(0) 46 , m_terminationRequested(false) 47 { 48 } 49 50 DatabaseThread::~DatabaseThread() 51 { 52 if (!m_terminationRequested) 53 requestTermination(0); 54 m_thread.clear(); 55 } 56 57 void DatabaseThread::start() 58 { 59 if (m_thread) 60 return; 61 m_thread = adoptPtr(blink::Platform::current()->createThread("WebCore: Database")); 62 } 63 64 void DatabaseThread::requestTermination(DatabaseTaskSynchronizer *cleanupSync) 65 { 66 ASSERT(!m_terminationRequested); 67 m_terminationRequested = true; 68 m_cleanupSync = cleanupSync; 69 WTF_LOG(StorageAPI, "DatabaseThread %p was asked to terminate\n", this); 70 m_thread->postTask(new Task(WTF::bind(&DatabaseThread::cleanupDatabaseThread, this))); 71 } 72 73 bool DatabaseThread::terminationRequested(DatabaseTaskSynchronizer* taskSynchronizer) const 74 { 75 #ifndef NDEBUG 76 if (taskSynchronizer) 77 taskSynchronizer->setHasCheckedForTermination(); 78 #endif 79 80 return m_terminationRequested; 81 } 82 83 void DatabaseThread::cleanupDatabaseThread() 84 { 85 WTF_LOG(StorageAPI, "Cleaning up DatabaseThread %p", this); 86 87 // Clean up the list of all pending transactions on this database thread 88 m_transactionCoordinator->shutdown(); 89 90 // 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 91 // inconsistent or locked state. 92 if (m_openDatabaseSet.size() > 0) { 93 // As the call to close will modify the original set, we must take a copy to iterate over. 94 DatabaseSet openSetCopy; 95 openSetCopy.swap(m_openDatabaseSet); 96 DatabaseSet::iterator end = openSetCopy.end(); 97 for (DatabaseSet::iterator it = openSetCopy.begin(); it != end; ++it) 98 (*it).get()->close(); 99 } 100 101 if (m_cleanupSync) // Someone wanted to know when we were done cleaning up. 102 m_thread->postTask(new Task(WTF::bind(&DatabaseTaskSynchronizer::taskCompleted, m_cleanupSync))); 103 } 104 105 void DatabaseThread::recordDatabaseOpen(DatabaseBackend* database) 106 { 107 ASSERT(isDatabaseThread()); 108 ASSERT(database); 109 ASSERT(!m_openDatabaseSet.contains(database)); 110 m_openDatabaseSet.add(database); 111 } 112 113 void DatabaseThread::recordDatabaseClosed(DatabaseBackend* database) 114 { 115 ASSERT(isDatabaseThread()); 116 ASSERT(database); 117 ASSERT(m_terminationRequested || m_openDatabaseSet.contains(database)); 118 m_openDatabaseSet.remove(database); 119 } 120 121 bool DatabaseThread::isDatabaseOpen(DatabaseBackend* database) 122 { 123 ASSERT(isDatabaseThread()); 124 ASSERT(database); 125 return !m_terminationRequested && m_openDatabaseSet.contains(database); 126 } 127 128 void DatabaseThread::scheduleTask(PassOwnPtr<DatabaseTask> task) 129 { 130 ASSERT(m_thread); 131 ASSERT(!task->hasSynchronizer() || task->hasCheckedForTermination()); 132 // WebThread takes ownership of the task. 133 m_thread->postTask(task.leakPtr()); 134 } 135 136 } // namespace WebCore 137