Blink roll 25b6bd3a7a131ffe68d809546ad1a20707915cdc:3a503f41ae42e5b79cfcd2ff10e65afde...
[chromium-blink-merge.git] / content / browser / indexed_db / indexed_db_transaction_coordinator.cc
blobc00c5fb466fd508fcaa09747b4b4b6fcc102e8bc
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "content/browser/indexed_db/indexed_db_transaction_coordinator.h"
7 #include "base/basictypes.h"
8 #include "base/logging.h"
9 #include "content/browser/indexed_db/indexed_db_transaction.h"
10 #include "third_party/WebKit/public/platform/WebIDBTypes.h"
12 namespace content {
14 IndexedDBTransactionCoordinator::IndexedDBTransactionCoordinator() {}
16 IndexedDBTransactionCoordinator::~IndexedDBTransactionCoordinator() {
17 DCHECK(!queued_transactions_.size());
18 DCHECK(!started_transactions_.size());
21 void IndexedDBTransactionCoordinator::DidCreateTransaction(
22 scoped_refptr<IndexedDBTransaction> transaction) {
23 DCHECK(!queued_transactions_.count(transaction));
24 DCHECK(!started_transactions_.count(transaction));
25 DCHECK_EQ(IndexedDBTransaction::CREATED, transaction->state());
27 queued_transactions_.insert(transaction);
28 ProcessQueuedTransactions();
31 void IndexedDBTransactionCoordinator::DidFinishTransaction(
32 IndexedDBTransaction* transaction) {
33 if (queued_transactions_.count(transaction)) {
34 DCHECK(!started_transactions_.count(transaction));
35 queued_transactions_.erase(transaction);
36 } else {
37 DCHECK(started_transactions_.count(transaction));
38 started_transactions_.erase(transaction);
41 ProcessQueuedTransactions();
44 bool IndexedDBTransactionCoordinator::IsRunningVersionChangeTransaction()
45 const {
46 return !started_transactions_.empty() &&
47 (*started_transactions_.begin())->mode() ==
48 blink::WebIDBTransactionModeVersionChange;
51 #ifndef NDEBUG
52 // Verifies internal consistency while returning whether anything is found.
53 bool IndexedDBTransactionCoordinator::IsActive(
54 IndexedDBTransaction* transaction) {
55 bool found = false;
56 if (queued_transactions_.count(transaction))
57 found = true;
58 if (started_transactions_.count(transaction)) {
59 DCHECK(!found);
60 found = true;
62 return found;
64 #endif
66 std::vector<const IndexedDBTransaction*>
67 IndexedDBTransactionCoordinator::GetTransactions() const {
68 std::vector<const IndexedDBTransaction*> result;
70 for (const auto& transaction : started_transactions_)
71 result.push_back(transaction.get());
72 for (const auto& transaction : queued_transactions_)
73 result.push_back(transaction.get());
75 return result;
78 void IndexedDBTransactionCoordinator::ProcessQueuedTransactions() {
79 if (queued_transactions_.empty())
80 return;
82 DCHECK(!IsRunningVersionChangeTransaction());
84 // The locked_scope set accumulates the ids of object stores in the scope of
85 // running read/write transactions. Other read-write transactions with
86 // stores in this set may not be started. Read-only transactions may start,
87 // taking a snapshot of the database, which does not include uncommitted
88 // data. ("Version change" transactions are exclusive, but handled by the
89 // connection sequencing in IndexedDBDatabase.)
90 std::set<int64> locked_scope;
91 for (const auto& transaction : started_transactions_) {
92 if (transaction->mode() == blink::WebIDBTransactionModeReadWrite) {
93 // Started read/write transactions have exclusive access to the object
94 // stores within their scopes.
95 locked_scope.insert(transaction->scope().begin(),
96 transaction->scope().end());
100 TransactionSet::const_iterator it = queued_transactions_.begin();
101 while (it != queued_transactions_.end()) {
102 scoped_refptr<IndexedDBTransaction> transaction = *it;
103 ++it;
104 if (CanStartTransaction(transaction.get(), locked_scope)) {
105 DCHECK_EQ(IndexedDBTransaction::CREATED, transaction->state());
106 queued_transactions_.erase(transaction);
107 started_transactions_.insert(transaction);
108 transaction->Start();
109 DCHECK_EQ(IndexedDBTransaction::STARTED, transaction->state());
111 if (transaction->mode() == blink::WebIDBTransactionModeReadWrite) {
112 // Either the transaction started, so it has exclusive access to the
113 // stores in its scope, or per the spec the transaction which was
114 // created first must get access first, so the stores are also locked.
115 locked_scope.insert(transaction->scope().begin(),
116 transaction->scope().end());
121 template<typename T>
122 static bool DoSetsIntersect(const std::set<T>& set1,
123 const std::set<T>& set2) {
124 typename std::set<T>::const_iterator it1 = set1.begin();
125 typename std::set<T>::const_iterator it2 = set2.begin();
126 while (it1 != set1.end() && it2 != set2.end()) {
127 if (*it1 < *it2)
128 ++it1;
129 else if (*it2 < *it1)
130 ++it2;
131 else
132 return true;
134 return false;
137 bool IndexedDBTransactionCoordinator::CanStartTransaction(
138 IndexedDBTransaction* const transaction,
139 const std::set<int64>& locked_scope) const {
140 DCHECK(queued_transactions_.count(transaction));
141 switch (transaction->mode()) {
142 case blink::WebIDBTransactionModeVersionChange:
143 DCHECK_EQ(1u, queued_transactions_.size());
144 DCHECK(started_transactions_.empty());
145 DCHECK(locked_scope.empty());
146 return true;
148 case blink::WebIDBTransactionModeReadOnly:
149 case blink::WebIDBTransactionModeReadWrite:
150 return !DoSetsIntersect(transaction->scope(), locked_scope);
152 NOTREACHED();
153 return false;
156 } // namespace content