1231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block/*
2231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * Copyright (C) 2009 Google Inc. All rights reserved.
3231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block *
4231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * Redistribution and use in source and binary forms, with or without
5231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * modification, are permitted provided that the following conditions are
6231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * met:
7231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block *
8231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block *     * Redistributions of source code must retain the above copyright
9231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * notice, this list of conditions and the following disclaimer.
10231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block *     * Redistributions in binary form must reproduce the above
11231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * copyright notice, this list of conditions and the following disclaimer
12231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * in the documentation and/or other materials provided with the
13231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * distribution.
14231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block *     * Neither the name of Google Inc. nor the names of its
15231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * contributors may be used to endorse or promote products derived from
16231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * this software without specific prior written permission.
17231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block *
18231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block */
30231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
31231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include "config.h"
32231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include "SQLTransactionCoordinator.h"
33231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
34d0825bca7fe65beaee391d30da42e937db621564Steve Block#if ENABLE(DATABASE)
35d0825bca7fe65beaee391d30da42e937db621564Steve Block
36231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include "Database.h"
37231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include "SQLTransaction.h"
38231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include <wtf/Deque.h>
39231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include <wtf/HashMap.h>
40231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include <wtf/HashSet.h>
41231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block#include <wtf/RefPtr.h>
42231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
43231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blocknamespace WebCore {
44231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
45231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockstatic String getDatabaseIdentifier(SQLTransaction* transaction)
46231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
47231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    Database* database = transaction->database();
48231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    ASSERT(database);
49231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    return database->stringIdentifier();
50231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
51231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
52231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockvoid SQLTransactionCoordinator::processPendingTransactions(CoordinationInfo& info)
53231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
54231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (info.activeWriteTransaction || info.pendingTransactions.isEmpty())
55231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return;
56231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
57231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    RefPtr<SQLTransaction> firstPendingTransaction = info.pendingTransactions.first();
58231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (firstPendingTransaction->isReadOnly()) {
59231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        do {
60545e470e52f0ac6a3a072bf559c796b42c6066b6Ben Murdoch            firstPendingTransaction = info.pendingTransactions.takeFirst();
61231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            info.activeReadTransactions.add(firstPendingTransaction);
62231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block            firstPendingTransaction->lockAcquired();
63231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        } while (!info.pendingTransactions.isEmpty() && info.pendingTransactions.first()->isReadOnly());
64231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    } else if (info.activeReadTransactions.isEmpty()) {
65231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        info.pendingTransactions.removeFirst();
66231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        info.activeWriteTransaction = firstPendingTransaction;
67231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        firstPendingTransaction->lockAcquired();
68231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
69231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
70231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
71231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockvoid SQLTransactionCoordinator::acquireLock(SQLTransaction* transaction)
72231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
73231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    String dbIdentifier = getDatabaseIdentifier(transaction);
74231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
75231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    CoordinationInfoMap::iterator coordinationInfoIterator = m_coordinationInfoMap.find(dbIdentifier);
76231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (coordinationInfoIterator == m_coordinationInfoMap.end()) {
77231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        // No pending transactions for this DB
78231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        coordinationInfoIterator = m_coordinationInfoMap.add(dbIdentifier, CoordinationInfo()).first;
79231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
80231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
81231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    CoordinationInfo& info = coordinationInfoIterator->second;
82231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    info.pendingTransactions.append(transaction);
83231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    processPendingTransactions(info);
84231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
85231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
86231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockvoid SQLTransactionCoordinator::releaseLock(SQLTransaction* transaction)
87231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
88231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (m_coordinationInfoMap.isEmpty())
89231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        return;
90231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
91231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    String dbIdentifier = getDatabaseIdentifier(transaction);
92231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
93231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    CoordinationInfoMap::iterator coordinationInfoIterator = m_coordinationInfoMap.find(dbIdentifier);
94231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    ASSERT(coordinationInfoIterator != m_coordinationInfoMap.end());
95231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    CoordinationInfo& info = coordinationInfoIterator->second;
96231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
97231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    if (transaction->isReadOnly()) {
98231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        ASSERT(info.activeReadTransactions.contains(transaction));
99231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        info.activeReadTransactions.remove(transaction);
100231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    } else {
101231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        ASSERT(info.activeWriteTransaction == transaction);
102231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block        info.activeWriteTransaction = 0;
103231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    }
104231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
105231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    processPendingTransactions(info);
106231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
107231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
108231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Blockvoid SQLTransactionCoordinator::shutdown()
109231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block{
1105e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block    // Notify all transactions in progress that the database thread is shutting down
1115e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block    for (CoordinationInfoMap::iterator coordinationInfoIterator = m_coordinationInfoMap.begin();
1125e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block         coordinationInfoIterator != m_coordinationInfoMap.end(); ++coordinationInfoIterator) {
1135e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        CoordinationInfo& info = coordinationInfoIterator->second;
1145e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        if (info.activeWriteTransaction)
1155e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block            info.activeWriteTransaction->notifyDatabaseThreadIsShuttingDown();
1165e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        for (HashSet<RefPtr<SQLTransaction> >::iterator activeReadTransactionsIterator =
1175e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block                     info.activeReadTransactions.begin();
1185e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block             activeReadTransactionsIterator != info.activeReadTransactions.end();
1195e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block             ++activeReadTransactionsIterator) {
1205e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block            (*activeReadTransactionsIterator)->notifyDatabaseThreadIsShuttingDown();
1215e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block        }
1225e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block    }
1235e2bc6953fe6923165b8a5d7679939693a1d58d6Steve Block
124231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    // Clean up all pending transactions for all databases
125231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block    m_coordinationInfoMap.clear();
126231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block}
127231d4e3152a9c27a73b6ac7badbe6be673aa3ddfSteve Block
128d0825bca7fe65beaee391d30da42e937db621564Steve Block} // namespace WebCore
129d0825bca7fe65beaee391d30da42e937db621564Steve Block
130d0825bca7fe65beaee391d30da42e937db621564Steve Block#endif // ENABLE(DATABASE)
131