Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1036)

Side by Side Diff: content/browser/indexed_db/indexed_db_transaction_coordinator.cc

Issue 2691423005: [IndexedDB] Transaction limitting (Closed)
Patch Set: Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « content/browser/indexed_db/indexed_db_transaction_coordinator.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "content/browser/indexed_db/indexed_db_transaction_coordinator.h" 5 #include "content/browser/indexed_db/indexed_db_transaction_coordinator.h"
6 6
7 #include "base/logging.h" 7 #include "base/logging.h"
8 #include "content/browser/indexed_db/indexed_db_tracing.h"
8 #include "content/browser/indexed_db/indexed_db_transaction.h" 9 #include "content/browser/indexed_db/indexed_db_transaction.h"
9 #include "third_party/WebKit/public/platform/modules/indexeddb/WebIDBTypes.h" 10 #include "third_party/WebKit/public/platform/modules/indexeddb/WebIDBTypes.h"
10 11
11 namespace content { 12 namespace content {
13 namespace {
14 static const size_t kMaxStartedTransactions = 10;
cmumford 2017/02/16 23:16:05 Can you add a comment explaining why this has a va
pwnall 2017/02/16 23:19:40 Can you explain that this limits the number of tra
dmurph 2017/02/16 23:32:34 Done.
15 } // namespace
12 16
13 IndexedDBTransactionCoordinator::IndexedDBTransactionCoordinator() {} 17 IndexedDBTransactionCoordinator::IndexedDBTransactionCoordinator() {}
14 18
15 IndexedDBTransactionCoordinator::~IndexedDBTransactionCoordinator() { 19 IndexedDBTransactionCoordinator::~IndexedDBTransactionCoordinator() {
16 DCHECK(queued_transactions_.empty()); 20 DCHECK(queued_transactions_.empty());
17 DCHECK(started_transactions_.empty()); 21 DCHECK(started_transactions_.empty());
18 } 22 }
19 23
20 void IndexedDBTransactionCoordinator::DidCreateTransaction( 24 void IndexedDBTransactionCoordinator::DidCreateTransaction(
21 IndexedDBTransaction* transaction) { 25 IndexedDBTransaction* transaction) {
22 DCHECK(!queued_transactions_.count(transaction)); 26 DCHECK(!queued_transactions_.count(transaction));
23 DCHECK(!started_transactions_.count(transaction)); 27 DCHECK(!started_transactions_.count(transaction));
24 DCHECK_EQ(IndexedDBTransaction::CREATED, transaction->state()); 28 DCHECK_EQ(IndexedDBTransaction::CREATED, transaction->state());
25 29
26 queued_transactions_.insert(transaction); 30 queued_transactions_.insert(transaction);
27 ProcessQueuedTransactions(); 31 ProcessQueuedTransactions();
28 } 32 }
29 33
30 // Observer transactions jump to the front of the queue. 34 // Observer transactions jump to the front of the queue.
31 void IndexedDBTransactionCoordinator::DidCreateObserverTransaction( 35 void IndexedDBTransactionCoordinator::DidCreateObserverTransaction(
32 IndexedDBTransaction* transaction) { 36 IndexedDBTransaction* transaction) {
33 DCHECK(!queued_transactions_.count(transaction)); 37 DCHECK(!queued_transactions_.count(transaction));
34 DCHECK(!started_transactions_.count(transaction)); 38 DCHECK(!started_transactions_.count(transaction));
35 DCHECK_EQ(IndexedDBTransaction::CREATED, transaction->state()); 39 DCHECK_EQ(IndexedDBTransaction::CREATED, transaction->state());
36 40
37 started_transactions_.insert_front(transaction); 41 started_transactions_.insert_front(transaction);
42 RecordMetrics();
38 ProcessQueuedTransactions(); 43 ProcessQueuedTransactions();
39 } 44 }
40 45
41 void IndexedDBTransactionCoordinator::DidFinishTransaction( 46 void IndexedDBTransactionCoordinator::DidFinishTransaction(
42 IndexedDBTransaction* transaction) { 47 IndexedDBTransaction* transaction) {
43 if (queued_transactions_.count(transaction)) { 48 if (queued_transactions_.count(transaction)) {
44 DCHECK(!started_transactions_.count(transaction)); 49 DCHECK(!started_transactions_.count(transaction));
45 queued_transactions_.erase(transaction); 50 queued_transactions_.erase(transaction);
46 } else { 51 } else {
47 DCHECK(started_transactions_.count(transaction)); 52 DCHECK(started_transactions_.count(transaction));
48 started_transactions_.erase(transaction); 53 started_transactions_.erase(transaction);
49 } 54 }
50 55 RecordMetrics();
51 ProcessQueuedTransactions(); 56 ProcessQueuedTransactions();
52 } 57 }
53 58
54 bool IndexedDBTransactionCoordinator::IsRunningVersionChangeTransaction() 59 bool IndexedDBTransactionCoordinator::IsRunningVersionChangeTransaction()
55 const { 60 const {
56 return !started_transactions_.empty() && 61 return !started_transactions_.empty() &&
57 (*started_transactions_.begin())->mode() == 62 (*started_transactions_.begin())->mode() ==
58 blink::WebIDBTransactionModeVersionChange; 63 blink::WebIDBTransactionModeVersionChange;
59 } 64 }
60 65
(...skipping 16 matching lines...) Expand all
77 IndexedDBTransactionCoordinator::GetTransactions() const { 82 IndexedDBTransactionCoordinator::GetTransactions() const {
78 std::vector<const IndexedDBTransaction*> result; 83 std::vector<const IndexedDBTransaction*> result;
79 result.reserve(started_transactions_.size() + queued_transactions_.size()); 84 result.reserve(started_transactions_.size() + queued_transactions_.size());
80 result.insert(result.end(), started_transactions_.begin(), 85 result.insert(result.end(), started_transactions_.begin(),
81 started_transactions_.end()); 86 started_transactions_.end());
82 result.insert(result.end(), queued_transactions_.begin(), 87 result.insert(result.end(), queued_transactions_.begin(),
83 queued_transactions_.end()); 88 queued_transactions_.end());
84 return result; 89 return result;
85 } 90 }
86 91
92 void IndexedDBTransactionCoordinator::RecordMetrics() const {
93 IDB_TRACE_COUNTER2("TransactionCoordinator", "StartedTransactions",
94 started_transactions_.size(), "QueuedTransactions",
95 queued_transactions_.size());
96 }
97
87 void IndexedDBTransactionCoordinator::ProcessQueuedTransactions() { 98 void IndexedDBTransactionCoordinator::ProcessQueuedTransactions() {
88 if (queued_transactions_.empty()) 99 if (queued_transactions_.empty())
89 return; 100 return;
90 101
91 DCHECK(!IsRunningVersionChangeTransaction()); 102 DCHECK(!IsRunningVersionChangeTransaction());
92 103
93 // The locked_scope set accumulates the ids of object stores in the scope of 104 // The locked_scope set accumulates the ids of object stores in the scope of
94 // running read/write transactions. Other read-write transactions with 105 // running read/write transactions. Other read-write transactions with
95 // stores in this set may not be started. Read-only transactions may start, 106 // stores in this set may not be started. Read-only transactions may start,
96 // taking a snapshot of the database, which does not include uncommitted 107 // taking a snapshot of the database, which does not include uncommitted
97 // data. ("Version change" transactions are exclusive, but handled by the 108 // data. ("Version change" transactions are exclusive, but handled by the
98 // connection sequencing in IndexedDBDatabase.) 109 // connection sequencing in IndexedDBDatabase.)
99 std::set<int64_t> locked_scope; 110 std::set<int64_t> locked_scope;
100 for (const auto& transaction : started_transactions_) { 111 for (const auto& transaction : started_transactions_) {
101 if (transaction->mode() == blink::WebIDBTransactionModeReadWrite) { 112 if (transaction->mode() == blink::WebIDBTransactionModeReadWrite) {
102 // Started read/write transactions have exclusive access to the object 113 // Started read/write transactions have exclusive access to the object
103 // stores within their scopes. 114 // stores within their scopes.
104 locked_scope.insert(transaction->scope().begin(), 115 locked_scope.insert(transaction->scope().begin(),
105 transaction->scope().end()); 116 transaction->scope().end());
106 } 117 }
107 } 118 }
108 119
109 auto it = queued_transactions_.begin(); 120 auto it = queued_transactions_.begin();
110 while (it != queued_transactions_.end()) { 121 while (it != queued_transactions_.end()) {
111 IndexedDBTransaction* transaction = *it; 122 IndexedDBTransaction* transaction = *it;
112 ++it; 123 ++it;
113 if (CanStartTransaction(transaction, locked_scope)) { 124 if (CanStartTransaction(transaction, locked_scope,
125 started_transactions_.size())) {
114 DCHECK_EQ(IndexedDBTransaction::CREATED, transaction->state()); 126 DCHECK_EQ(IndexedDBTransaction::CREATED, transaction->state());
115 queued_transactions_.erase(transaction); 127 queued_transactions_.erase(transaction);
116 started_transactions_.insert(transaction); 128 started_transactions_.insert(transaction);
117 transaction->Start(); 129 transaction->Start();
118 DCHECK_EQ(IndexedDBTransaction::STARTED, transaction->state()); 130 DCHECK_EQ(IndexedDBTransaction::STARTED, transaction->state());
119 } 131 }
120 if (transaction->mode() == blink::WebIDBTransactionModeReadWrite) { 132 if (transaction->mode() == blink::WebIDBTransactionModeReadWrite) {
121 // Either the transaction started, so it has exclusive access to the 133 // Either the transaction started, so it has exclusive access to the
122 // stores in its scope, or per the spec the transaction which was 134 // stores in its scope, or per the spec the transaction which was
123 // created first must get access first, so the stores are also locked. 135 // created first must get access first, so the stores are also locked.
124 locked_scope.insert(transaction->scope().begin(), 136 locked_scope.insert(transaction->scope().begin(),
125 transaction->scope().end()); 137 transaction->scope().end());
126 } 138 }
127 } 139 }
140 RecordMetrics();
128 } 141 }
129 142
130 template<typename T> 143 template<typename T>
131 static bool DoSetsIntersect(const std::set<T>& set1, 144 static bool DoSetsIntersect(const std::set<T>& set1,
132 const std::set<T>& set2) { 145 const std::set<T>& set2) {
133 typename std::set<T>::const_iterator it1 = set1.begin(); 146 typename std::set<T>::const_iterator it1 = set1.begin();
134 typename std::set<T>::const_iterator it2 = set2.begin(); 147 typename std::set<T>::const_iterator it2 = set2.begin();
135 while (it1 != set1.end() && it2 != set2.end()) { 148 while (it1 != set1.end() && it2 != set2.end()) {
136 if (*it1 < *it2) 149 if (*it1 < *it2)
137 ++it1; 150 ++it1;
138 else if (*it2 < *it1) 151 else if (*it2 < *it1)
139 ++it2; 152 ++it2;
140 else 153 else
141 return true; 154 return true;
142 } 155 }
143 return false; 156 return false;
144 } 157 }
145 158
146 bool IndexedDBTransactionCoordinator::CanStartTransaction( 159 bool IndexedDBTransactionCoordinator::CanStartTransaction(
147 IndexedDBTransaction* const transaction, 160 IndexedDBTransaction* const transaction,
148 const std::set<int64_t>& locked_scope) const { 161 const std::set<int64_t>& locked_scope,
162 size_t num_started_txns) const {
cmumford 2017/02/16 23:16:05 This is a non-static member function. Why not just
dmurph 2017/02/16 23:32:34 Whoops, yes much better.
163 if (num_started_txns >= kMaxStartedTransactions) {
164 return false;
165 }
149 DCHECK(queued_transactions_.count(transaction)); 166 DCHECK(queued_transactions_.count(transaction));
150 switch (transaction->mode()) { 167 switch (transaction->mode()) {
151 case blink::WebIDBTransactionModeVersionChange: 168 case blink::WebIDBTransactionModeVersionChange:
152 DCHECK_EQ(1u, queued_transactions_.size()); 169 DCHECK_EQ(1u, queued_transactions_.size());
153 DCHECK(started_transactions_.empty()); 170 DCHECK(started_transactions_.empty());
154 DCHECK(locked_scope.empty()); 171 DCHECK(locked_scope.empty());
155 return true; 172 return true;
156 173
157 case blink::WebIDBTransactionModeReadOnly: 174 case blink::WebIDBTransactionModeReadOnly:
158 case blink::WebIDBTransactionModeReadWrite: 175 case blink::WebIDBTransactionModeReadWrite:
159 return !DoSetsIntersect(transaction->scope(), locked_scope); 176 return !DoSetsIntersect(transaction->scope(), locked_scope);
160 } 177 }
161 NOTREACHED(); 178 NOTREACHED();
162 return false; 179 return false;
163 } 180 }
164 181
165 } // namespace content 182 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/indexed_db/indexed_db_transaction_coordinator.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698