WebCore/storage/DatabaseThread.cpp
changeset 0 4f2f89ce4247
equal deleted inserted replaced
-1:000000000000 0:4f2f89ce4247
       
     1 /*
       
     2  * Copyright (C) 2007, 2008 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 "DatabaseThread.h"
       
    31 
       
    32 #if ENABLE(DATABASE)
       
    33 
       
    34 #include "AutodrainedPool.h"
       
    35 #include "Database.h"
       
    36 #include "DatabaseTask.h"
       
    37 #include "Logging.h"
       
    38 #include "SQLTransactionClient.h"
       
    39 #include "SQLTransactionCoordinator.h"
       
    40 
       
    41 namespace WebCore {
       
    42 
       
    43 DatabaseThread::DatabaseThread()
       
    44     : m_threadID(0)
       
    45     , m_transactionClient(new SQLTransactionClient())
       
    46     , m_transactionCoordinator(new SQLTransactionCoordinator())
       
    47     , m_cleanupSync(0)
       
    48 {
       
    49     m_selfRef = this;
       
    50 }
       
    51 
       
    52 DatabaseThread::~DatabaseThread()
       
    53 {
       
    54     // FIXME: Any cleanup required here?  Since the thread deletes itself after running its detached course, I don't think so.  Lets be sure.
       
    55     ASSERT(terminationRequested());
       
    56 }
       
    57 
       
    58 bool DatabaseThread::start()
       
    59 {
       
    60     MutexLocker lock(m_threadCreationMutex);
       
    61 
       
    62     if (m_threadID)
       
    63         return true;
       
    64 
       
    65     m_threadID = createThread(DatabaseThread::databaseThreadStart, this, "WebCore: Database");
       
    66 
       
    67     return m_threadID;
       
    68 }
       
    69 
       
    70 void DatabaseThread::requestTermination(DatabaseTaskSynchronizer *cleanupSync)
       
    71 {
       
    72     ASSERT(!m_cleanupSync);
       
    73     m_cleanupSync = cleanupSync;
       
    74     LOG(StorageAPI, "DatabaseThread %p was asked to terminate\n", this);
       
    75     m_queue.kill();
       
    76 }
       
    77 
       
    78 bool DatabaseThread::terminationRequested() const
       
    79 {
       
    80     return m_queue.killed();
       
    81 }
       
    82 
       
    83 void* DatabaseThread::databaseThreadStart(void* vDatabaseThread)
       
    84 {
       
    85     DatabaseThread* dbThread = static_cast<DatabaseThread*>(vDatabaseThread);
       
    86     return dbThread->databaseThread();
       
    87 }
       
    88 
       
    89 void* DatabaseThread::databaseThread()
       
    90 {
       
    91     {
       
    92         // Wait for DatabaseThread::start() to complete.
       
    93         MutexLocker lock(m_threadCreationMutex);
       
    94         LOG(StorageAPI, "Started DatabaseThread %p", this);
       
    95     }
       
    96 
       
    97     AutodrainedPool pool;
       
    98     while (OwnPtr<DatabaseTask> task = m_queue.waitForMessage()) {
       
    99         task->performTask();
       
   100         pool.cycle();
       
   101     }
       
   102 
       
   103     // Clean up the list of all pending transactions on this database thread
       
   104     m_transactionCoordinator->shutdown();
       
   105 
       
   106     LOG(StorageAPI, "About to detach thread %i and clear the ref to DatabaseThread %p, which currently has %i ref(s)", m_threadID, this, refCount());
       
   107 
       
   108     // 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
       
   109     // inconsistent or locked state.
       
   110     if (m_openDatabaseSet.size() > 0) {
       
   111         // As the call to close will modify the original set, we must take a copy to iterate over.
       
   112         DatabaseSet openSetCopy;
       
   113         openSetCopy.swap(m_openDatabaseSet);
       
   114         DatabaseSet::iterator end = openSetCopy.end();
       
   115         for (DatabaseSet::iterator it = openSetCopy.begin(); it != end; ++it)
       
   116             (*it)->close();
       
   117     }
       
   118 
       
   119     // Detach the thread so its resources are no longer of any concern to anyone else
       
   120     detachThread(m_threadID);
       
   121 
       
   122     DatabaseTaskSynchronizer* cleanupSync = m_cleanupSync;
       
   123 
       
   124     // Clear the self refptr, possibly resulting in deletion
       
   125     m_selfRef = 0;
       
   126 
       
   127     if (cleanupSync) // Someone wanted to know when we were done cleaning up.
       
   128         cleanupSync->taskCompleted();
       
   129 
       
   130     return 0;
       
   131 }
       
   132 
       
   133 void DatabaseThread::recordDatabaseOpen(Database* database)
       
   134 {
       
   135     ASSERT(currentThread() == m_threadID);
       
   136     ASSERT(database);
       
   137     ASSERT(!m_openDatabaseSet.contains(database));
       
   138     m_openDatabaseSet.add(database);
       
   139 }
       
   140 
       
   141 void DatabaseThread::recordDatabaseClosed(Database* database)
       
   142 {
       
   143     ASSERT(currentThread() == m_threadID);
       
   144     ASSERT(database);
       
   145     ASSERT(m_queue.killed() || m_openDatabaseSet.contains(database));
       
   146     m_openDatabaseSet.remove(database);
       
   147 }
       
   148 
       
   149 void DatabaseThread::scheduleTask(PassOwnPtr<DatabaseTask> task)
       
   150 {
       
   151     m_queue.append(task);
       
   152 }
       
   153 
       
   154 void DatabaseThread::scheduleImmediateTask(PassOwnPtr<DatabaseTask> task)
       
   155 {
       
   156     m_queue.prepend(task);
       
   157 }
       
   158 
       
   159 class SameDatabasePredicate {
       
   160 public:
       
   161     SameDatabasePredicate(const Database* database) : m_database(database) { }
       
   162     bool operator()(DatabaseTask* task) const { return task->database() == m_database; }
       
   163 private:
       
   164     const Database* m_database;
       
   165 };
       
   166 
       
   167 void DatabaseThread::unscheduleDatabaseTasks(Database* database)
       
   168 {
       
   169     // Note that the thread loop is running, so some tasks for the database
       
   170     // may still be executed. This is unavoidable.
       
   171     SameDatabasePredicate predicate(database);
       
   172     m_queue.removeIf(predicate);
       
   173 }
       
   174 } // namespace WebCore
       
   175 #endif