OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "content/browser/indexed_db/indexed_db_transaction_coordinator.h" | |
6 | |
7 #include "base/basictypes.h" | |
8 #include "base/logging.h" | |
9 #include "content/browser/indexed_db/indexed_db_transaction.h" | |
10 | |
11 namespace content { | |
12 | |
13 IndexedDBTransactionCoordinator::IndexedDBTransactionCoordinator() {} | |
14 | |
15 IndexedDBTransactionCoordinator::~IndexedDBTransactionCoordinator() { | |
16 // TODO(jsbell): DCHECK that all queues are empty. http://crbug.com/241821 | |
17 } | |
18 | |
19 void IndexedDBTransactionCoordinator::DidCreateTransaction( | |
20 IndexedDBTransaction* transaction) { | |
21 DCHECK(transactions_.find(transaction) == transactions_.end()); | |
22 transactions_[transaction] = transaction; | |
23 } | |
24 | |
25 void IndexedDBTransactionCoordinator::DidStartTransaction( | |
26 IndexedDBTransaction* transaction) { | |
27 DCHECK(transactions_.find(transaction) != transactions_.end()); | |
28 | |
29 queued_transactions_.insert(transaction); | |
30 ProcessStartedTransactions(); | |
31 } | |
32 | |
33 void IndexedDBTransactionCoordinator::DidFinishTransaction( | |
34 IndexedDBTransaction* transaction) { | |
35 DCHECK(transactions_.find(transaction) != transactions_.end()); | |
36 | |
37 if (queued_transactions_.has(transaction)) { | |
38 DCHECK(started_transactions_.find(transaction) == | |
39 started_transactions_.end()); | |
40 queued_transactions_.erase(transaction); | |
41 } else { | |
42 if (started_transactions_.find(transaction) != started_transactions_.end()) | |
43 started_transactions_.erase(transaction); | |
44 } | |
45 transactions_.erase(transaction); | |
46 | |
47 ProcessStartedTransactions(); | |
48 } | |
49 | |
50 #ifndef NDEBUG | |
51 // Verifies internal consistency while returning whether anything is found. | |
52 bool IndexedDBTransactionCoordinator::IsActive( | |
53 IndexedDBTransaction* transaction) { | |
54 bool found = false; | |
55 if (queued_transactions_.has(transaction)) | |
56 found = true; | |
57 if (started_transactions_.find(transaction) != started_transactions_.end()) { | |
58 DCHECK(!found); | |
59 found = true; | |
60 } | |
61 DCHECK_EQ(found, (transactions_.find(transaction) != transactions_.end())); | |
62 return found; | |
63 } | |
64 #endif | |
65 | |
66 void IndexedDBTransactionCoordinator::ProcessStartedTransactions() { | |
67 if (queued_transactions_.empty()) | |
68 return; | |
69 | |
70 DCHECK(started_transactions_.empty() || | |
71 (*started_transactions_.begin())->mode() != | |
72 indexed_db::TRANSACTION_VERSION_CHANGE); | |
73 | |
74 list_set<IndexedDBTransaction*>::const_iterator it = | |
75 queued_transactions_.begin(); | |
76 while (it != queued_transactions_.end()) { | |
77 IndexedDBTransaction* transaction = *it; | |
78 ++it; | |
79 if (CanRunTransaction(transaction)) { | |
80 queued_transactions_.erase(transaction); | |
81 started_transactions_.insert(transaction); | |
82 transaction->Run(); | |
83 } | |
84 } | |
85 } | |
86 | |
87 static bool DoScopesOverlap(const std::set<int64>& scope1, | |
88 const std::set<int64>& scope2) { | |
89 for (std::set<int64>::const_iterator it = scope1.begin(); it != scope1.end(); | |
90 ++it) { | |
91 if (scope2.find(*it) != scope2.end()) | |
92 return true; | |
93 } | |
94 return false; | |
95 } | |
96 | |
97 bool IndexedDBTransactionCoordinator::CanRunTransaction( | |
98 IndexedDBTransaction* transaction) { | |
99 DCHECK(queued_transactions_.has(transaction)); | |
100 switch (transaction->mode()) { | |
101 case indexed_db::TRANSACTION_VERSION_CHANGE: | |
102 DCHECK(queued_transactions_.size() == 1); | |
103 DCHECK(started_transactions_.empty()); | |
104 return true; | |
105 | |
106 case indexed_db::TRANSACTION_READ_ONLY: | |
107 return true; | |
108 | |
109 case indexed_db::TRANSACTION_READ_WRITE: | |
110 for (std::set<IndexedDBTransaction*>::const_iterator it = | |
111 started_transactions_.begin(); | |
112 it != started_transactions_.end(); | |
113 ++it) { | |
114 IndexedDBTransaction* other = *it; | |
115 if (other->mode() == indexed_db::TRANSACTION_READ_WRITE && | |
116 DoScopesOverlap(transaction->scope(), other->scope())) | |
117 return false; | |
118 } | |
119 for (list_set<IndexedDBTransaction*>::const_iterator it = | |
120 queued_transactions_.begin(); | |
121 *it != transaction; | |
122 ++it) { | |
123 DCHECK(it != queued_transactions_.end()); | |
124 IndexedDBTransaction* other = *it; | |
125 if (other->mode() == indexed_db::TRANSACTION_READ_WRITE && | |
126 DoScopesOverlap(transaction->scope(), other->scope())) | |
127 return false; | |
128 } | |
129 return true; | |
130 } | |
131 NOTREACHED(); | |
132 return false; | |
133 } | |
134 | |
135 } // namespace content | |
OLD | NEW |