- add third_party src.
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / 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 "modules/webdatabase/DatabaseBackend.h"
28
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"
40
41 namespace WebCore {
42
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)
47 {
48 }
49
50 bool DatabaseBackend::openAndVerifyVersion(bool setVersionInNewDatabase, DatabaseError& error, String& errorMessage)
51 {
52     DatabaseTaskSynchronizer synchronizer;
53     if (!databaseContext()->databaseThread() || databaseContext()->databaseThread()->terminationRequested(&synchronizer))
54         return false;
55
56     DatabaseTracker::tracker().prepareToOpenDatabase(this);
57     bool success = false;
58     OwnPtr<DatabaseOpenTask> task = DatabaseOpenTask::create(this, setVersionInNewDatabase, &synchronizer, error, errorMessage, success);
59     databaseContext()->databaseThread()->scheduleImmediateTask(task.release());
60     synchronizer.waitForTaskCompletion();
61
62     return success;
63 }
64
65 bool DatabaseBackend::performOpenAndVerify(bool setVersionInNewDatabase, DatabaseError& error, String& errorMessage)
66 {
67     if (DatabaseBackendBase::performOpenAndVerify(setVersionInNewDatabase, error, errorMessage)) {
68         if (databaseContext()->databaseThread())
69             databaseContext()->databaseThread()->recordDatabaseOpen(this);
70
71         return true;
72     }
73
74     return false;
75 }
76
77 void DatabaseBackend::close()
78 {
79     ASSERT(databaseContext()->databaseThread());
80     ASSERT(currentThread() == databaseContext()->databaseThread()->getThreadID());
81
82     {
83         MutexLocker locker(m_transactionInProgressMutex);
84
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();
92         }
93
94         m_isTransactionQueueEnabled = false;
95         m_transactionInProgress = false;
96     }
97
98     closeDatabase();
99
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
105     // deleted.
106     RefPtr<DatabaseBackend> protect = this;
107     databaseContext()->databaseThread()->recordDatabaseClosed(this);
108     databaseContext()->databaseThread()->unscheduleDatabaseTasks(this);
109 }
110
111 PassRefPtr<SQLTransactionBackend> DatabaseBackend::runTransaction(PassRefPtr<SQLTransaction> transaction,
112     bool readOnly, const ChangeVersionData* data)
113 {
114     MutexLocker locker(m_transactionInProgressMutex);
115     if (!m_isTransactionQueueEnabled)
116         return 0;
117
118     RefPtr<SQLTransactionWrapper> wrapper;
119     if (data)
120         wrapper = ChangeVersionWrapper::create(data->oldVersion(), data->newVersion());
121
122     RefPtr<SQLTransactionBackend> transactionBackend = SQLTransactionBackend::create(this, transaction, wrapper, readOnly);
123     m_transactionQueue.append(transactionBackend);
124     if (!m_transactionInProgress)
125         scheduleTransaction();
126
127     return transactionBackend;
128 }
129
130 void DatabaseBackend::inProgressTransactionCompleted()
131 {
132     MutexLocker locker(m_transactionInProgressMutex);
133     m_transactionInProgress = false;
134     scheduleTransaction();
135 }
136
137 void DatabaseBackend::scheduleTransaction()
138 {
139     ASSERT(!m_transactionInProgressMutex.tryLock()); // Locked by caller.
140     RefPtr<SQLTransactionBackend> transaction;
141
142     if (m_isTransactionQueueEnabled && !m_transactionQueue.isEmpty())
143         transaction = m_transactionQueue.takeFirst();
144
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());
150     } else
151         m_transactionInProgress = false;
152 }
153
154 void DatabaseBackend::scheduleTransactionStep(SQLTransactionBackend* transaction)
155 {
156     if (!databaseContext()->databaseThread())
157         return;
158
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());
162 }
163
164 SQLTransactionClient* DatabaseBackend::transactionClient() const
165 {
166     return databaseContext()->databaseThread()->transactionClient();
167 }
168
169 SQLTransactionCoordinator* DatabaseBackend::transactionCoordinator() const
170 {
171     return databaseContext()->databaseThread()->transactionCoordinator();
172 }
173
174 } // namespace WebCore