2 * Copyright (C) 2013 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 #include "modules/webdatabase/DatabaseBackend.h"
29 #include "platform/Logging.h"
30 #include "modules/webdatabase/ChangeVersionData.h"
31 #include "modules/webdatabase/ChangeVersionWrapper.h"
32 #include "modules/webdatabase/DatabaseContext.h"
33 #include "modules/webdatabase/DatabaseTask.h"
34 #include "modules/webdatabase/DatabaseThread.h"
35 #include "modules/webdatabase/DatabaseTracker.h"
36 #include "modules/webdatabase/SQLTransaction.h"
37 #include "modules/webdatabase/SQLTransactionBackend.h"
38 #include "modules/webdatabase/SQLTransactionClient.h"
39 #include "modules/webdatabase/SQLTransactionCoordinator.h"
43 DatabaseBackend::DatabaseBackend(PassRefPtr<DatabaseContext> databaseContext, const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize)
44 : DatabaseBackendBase(databaseContext, name, expectedVersion, displayName, estimatedSize, DatabaseType::Async)
45 , m_transactionInProgress(false)
46 , m_isTransactionQueueEnabled(true)
50 bool DatabaseBackend::openAndVerifyVersion(bool setVersionInNewDatabase, DatabaseError& error, String& errorMessage)
52 DatabaseTaskSynchronizer synchronizer;
53 if (!databaseContext()->databaseThread() || databaseContext()->databaseThread()->terminationRequested(&synchronizer))
56 DatabaseTracker::tracker().prepareToOpenDatabase(this);
58 OwnPtr<DatabaseOpenTask> task = DatabaseOpenTask::create(this, setVersionInNewDatabase, &synchronizer, error, errorMessage, success);
59 databaseContext()->databaseThread()->scheduleImmediateTask(task.release());
60 synchronizer.waitForTaskCompletion();
65 bool DatabaseBackend::performOpenAndVerify(bool setVersionInNewDatabase, DatabaseError& error, String& errorMessage)
67 if (DatabaseBackendBase::performOpenAndVerify(setVersionInNewDatabase, error, errorMessage)) {
68 if (databaseContext()->databaseThread())
69 databaseContext()->databaseThread()->recordDatabaseOpen(this);
77 void DatabaseBackend::close()
79 ASSERT(databaseContext()->databaseThread());
80 ASSERT(currentThread() == databaseContext()->databaseThread()->getThreadID());
83 MutexLocker locker(m_transactionInProgressMutex);
85 // Clean up transactions that have not been scheduled yet:
86 // Transaction phase 1 cleanup. See comment on "What happens if a
87 // transaction is interrupted?" at the top of SQLTransactionBackend.cpp.
88 RefPtr<SQLTransactionBackend> transaction;
89 while (!m_transactionQueue.isEmpty()) {
90 transaction = m_transactionQueue.takeFirst();
91 transaction->notifyDatabaseThreadIsShuttingDown();
94 m_isTransactionQueueEnabled = false;
95 m_transactionInProgress = false;
100 // DatabaseThread keeps databases alive by referencing them in its
101 // m_openDatabaseSet. DatabaseThread::recordDatabaseClose() will remove
102 // this database from that set (which effectively deref's it). We hold on
103 // to it with a local pointer here for a liitle longer, so that we can
104 // unschedule any DatabaseTasks that refer to it before the database gets
106 RefPtr<DatabaseBackend> protect = this;
107 databaseContext()->databaseThread()->recordDatabaseClosed(this);
108 databaseContext()->databaseThread()->unscheduleDatabaseTasks(this);
111 PassRefPtr<SQLTransactionBackend> DatabaseBackend::runTransaction(PassRefPtr<SQLTransaction> transaction,
112 bool readOnly, const ChangeVersionData* data)
114 MutexLocker locker(m_transactionInProgressMutex);
115 if (!m_isTransactionQueueEnabled)
118 RefPtr<SQLTransactionWrapper> wrapper;
120 wrapper = ChangeVersionWrapper::create(data->oldVersion(), data->newVersion());
122 RefPtr<SQLTransactionBackend> transactionBackend = SQLTransactionBackend::create(this, transaction, wrapper, readOnly);
123 m_transactionQueue.append(transactionBackend);
124 if (!m_transactionInProgress)
125 scheduleTransaction();
127 return transactionBackend;
130 void DatabaseBackend::inProgressTransactionCompleted()
132 MutexLocker locker(m_transactionInProgressMutex);
133 m_transactionInProgress = false;
134 scheduleTransaction();
137 void DatabaseBackend::scheduleTransaction()
139 ASSERT(!m_transactionInProgressMutex.tryLock()); // Locked by caller.
140 RefPtr<SQLTransactionBackend> transaction;
142 if (m_isTransactionQueueEnabled && !m_transactionQueue.isEmpty())
143 transaction = m_transactionQueue.takeFirst();
145 if (transaction && databaseContext()->databaseThread()) {
146 OwnPtr<DatabaseTransactionTask> task = DatabaseTransactionTask::create(transaction);
147 LOG(StorageAPI, "Scheduling DatabaseTransactionTask %p for transaction %p\n", task.get(), task->transaction());
148 m_transactionInProgress = true;
149 databaseContext()->databaseThread()->scheduleTask(task.release());
151 m_transactionInProgress = false;
154 void DatabaseBackend::scheduleTransactionStep(SQLTransactionBackend* transaction)
156 if (!databaseContext()->databaseThread())
159 OwnPtr<DatabaseTransactionTask> task = DatabaseTransactionTask::create(transaction);
160 LOG(StorageAPI, "Scheduling DatabaseTransactionTask %p for the transaction step\n", task.get());
161 databaseContext()->databaseThread()->scheduleTask(task.release());
164 SQLTransactionClient* DatabaseBackend::transactionClient() const
166 return databaseContext()->databaseThread()->transactionClient();
169 SQLTransactionCoordinator* DatabaseBackend::transactionCoordinator() const
171 return databaseContext()->databaseThread()->transactionCoordinator();
174 } // namespace WebCore