Add WTF::move()
[WebKit-https.git] / Source / WebCore / Modules / webdatabase / DatabaseBackend.cpp
1 /*
2  * Copyright (C) 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  * 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.
12  *
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. 
24  */
25
26 #include "config.h"
27 #include "DatabaseBackend.h"
28
29 #if ENABLE(SQL_DATABASE)
30
31 #include "ChangeVersionData.h"
32 #include "ChangeVersionWrapper.h"
33 #include "DatabaseBackendContext.h"
34 #include "DatabaseTask.h"
35 #include "DatabaseThread.h"
36 #include "DatabaseTracker.h"
37 #include "Logging.h"
38 #include "SQLTransaction.h"
39 #include "SQLTransactionBackend.h"
40 #include "SQLTransactionClient.h"
41 #include "SQLTransactionCoordinator.h"
42
43 namespace WebCore {
44
45 DatabaseBackend::DatabaseBackend(PassRefPtr<DatabaseBackendContext> databaseContext, const String& name, const String& expectedVersion, const String& displayName, unsigned long estimatedSize)
46     : DatabaseBackendBase(databaseContext, name, expectedVersion, displayName, estimatedSize, DatabaseType::Async)
47     , m_transactionInProgress(false)
48     , m_isTransactionQueueEnabled(true)
49 {
50 }
51
52 bool DatabaseBackend::openAndVerifyVersion(bool setVersionInNewDatabase, DatabaseError& error, String& errorMessage)
53 {
54     DatabaseTaskSynchronizer synchronizer;
55     if (!databaseContext()->databaseThread() || databaseContext()->databaseThread()->terminationRequested(&synchronizer))
56         return false;
57
58     bool success = false;
59     auto task = DatabaseOpenTask::create(this, setVersionInNewDatabase, &synchronizer, error, errorMessage, success);
60     databaseContext()->databaseThread()->scheduleImmediateTask(WTF::move(task));
61     synchronizer.waitForTaskCompletion();
62
63     return success;
64 }
65
66 bool DatabaseBackend::performOpenAndVerify(bool setVersionInNewDatabase, DatabaseError& error, String& errorMessage)
67 {
68     if (DatabaseBackendBase::performOpenAndVerify(setVersionInNewDatabase, error, errorMessage)) {
69         if (databaseContext()->databaseThread())
70             databaseContext()->databaseThread()->recordDatabaseOpen(this);
71
72         return true;
73     }
74
75     return false;
76 }
77
78 void DatabaseBackend::close()
79 {
80     ASSERT(databaseContext()->databaseThread());
81     ASSERT(currentThread() == databaseContext()->databaseThread()->getThreadID());
82
83     {
84         MutexLocker locker(m_transactionInProgressMutex);
85
86         // Clean up transactions that have not been scheduled yet:
87         // Transaction phase 1 cleanup. See comment on "What happens if a
88         // transaction is interrupted?" at the top of SQLTransactionBackend.cpp.
89         RefPtr<SQLTransactionBackend> transaction;
90         while (!m_transactionQueue.isEmpty()) {
91             transaction = m_transactionQueue.takeFirst();
92             transaction->notifyDatabaseThreadIsShuttingDown();
93         }
94
95         m_isTransactionQueueEnabled = false;
96         m_transactionInProgress = false;
97     }
98
99     closeDatabase();
100
101     // DatabaseThread keeps databases alive by referencing them in its
102     // m_openDatabaseSet. DatabaseThread::recordDatabaseClose() will remove
103     // this database from that set (which effectively deref's it). We hold on
104     // to it with a local pointer here for a liitle longer, so that we can
105     // unschedule any DatabaseTasks that refer to it before the database gets
106     // deleted.
107     Ref<DatabaseBackend> protect(*this);
108     databaseContext()->databaseThread()->recordDatabaseClosed(this);
109     databaseContext()->databaseThread()->unscheduleDatabaseTasks(this);
110 }
111
112 PassRefPtr<SQLTransactionBackend> DatabaseBackend::runTransaction(PassRefPtr<SQLTransaction> transaction,
113     bool readOnly, const ChangeVersionData* data)
114 {
115     MutexLocker locker(m_transactionInProgressMutex);
116     if (!m_isTransactionQueueEnabled)
117         return 0;
118
119     RefPtr<SQLTransactionWrapper> wrapper;
120     if (data)
121         wrapper = ChangeVersionWrapper::create(data->oldVersion(), data->newVersion());
122
123     RefPtr<SQLTransactionBackend> transactionBackend = SQLTransactionBackend::create(this, transaction, wrapper, readOnly);
124     m_transactionQueue.append(transactionBackend);
125     if (!m_transactionInProgress)
126         scheduleTransaction();
127
128     return transactionBackend;
129 }
130
131 void DatabaseBackend::inProgressTransactionCompleted()
132 {
133     MutexLocker locker(m_transactionInProgressMutex);
134     m_transactionInProgress = false;
135     scheduleTransaction();
136 }
137
138 void DatabaseBackend::scheduleTransaction()
139 {
140     ASSERT(!m_transactionInProgressMutex.tryLock()); // Locked by caller.
141     RefPtr<SQLTransactionBackend> transaction;
142
143     if (m_isTransactionQueueEnabled && !m_transactionQueue.isEmpty())
144         transaction = m_transactionQueue.takeFirst();
145
146     if (transaction && databaseContext()->databaseThread()) {
147         auto task = DatabaseTransactionTask::create(transaction);
148         LOG(StorageAPI, "Scheduling DatabaseTransactionTask %p for transaction %p\n", task.get(), task->transaction());
149         m_transactionInProgress = true;
150         databaseContext()->databaseThread()->scheduleTask(WTF::move(task));
151     } else
152         m_transactionInProgress = false;
153 }
154
155 void DatabaseBackend::scheduleTransactionStep(SQLTransactionBackend* transaction)
156 {
157     if (!databaseContext()->databaseThread())
158         return;
159
160     auto task = DatabaseTransactionTask::create(transaction);
161     LOG(StorageAPI, "Scheduling DatabaseTransactionTask %p for the transaction step\n", task.get());
162     databaseContext()->databaseThread()->scheduleTask(WTF::move(task));
163 }
164
165 SQLTransactionClient* DatabaseBackend::transactionClient() const
166 {
167     return databaseContext()->databaseThread()->transactionClient();
168 }
169
170 SQLTransactionCoordinator* DatabaseBackend::transactionCoordinator() const
171 {
172     return databaseContext()->databaseThread()->transactionCoordinator();
173 }
174
175 } // namespace WebCore
176
177 #endif // ENABLE(SQL_DATABASE)