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

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

Issue 2506773002: [IndexedDB] Integrating failures and corruption with transaction (Closed)
Patch Set: Created 4 years, 1 month 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
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_cursor.h" 5 #include "content/browser/indexed_db/indexed_db_cursor.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 #include <utility> 8 #include <utility>
9 #include <vector> 9 #include <vector>
10 10
11 #include "base/bind.h" 11 #include "base/bind.h"
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "content/browser/indexed_db/indexed_db_callbacks.h" 13 #include "content/browser/indexed_db/indexed_db_callbacks.h"
14 #include "content/browser/indexed_db/indexed_db_database_error.h" 14 #include "content/browser/indexed_db/indexed_db_database_error.h"
15 #include "content/browser/indexed_db/indexed_db_tracing.h" 15 #include "content/browser/indexed_db/indexed_db_tracing.h"
16 #include "content/browser/indexed_db/indexed_db_transaction.h" 16 #include "content/browser/indexed_db/indexed_db_transaction.h"
17 #include "content/browser/indexed_db/indexed_db_value.h" 17 #include "content/browser/indexed_db/indexed_db_value.h"
18 #include "third_party/WebKit/public/platform/modules/indexeddb/WebIDBDatabaseExc eption.h"
18 19
19 namespace content { 20 namespace content {
20 21
21 IndexedDBCursor::IndexedDBCursor( 22 IndexedDBCursor::IndexedDBCursor(
22 std::unique_ptr<IndexedDBBackingStore::Cursor> cursor, 23 std::unique_ptr<IndexedDBBackingStore::Cursor> cursor,
23 indexed_db::CursorType cursor_type, 24 indexed_db::CursorType cursor_type,
24 blink::WebIDBTaskType task_type, 25 blink::WebIDBTaskType task_type,
25 IndexedDBTransaction* transaction) 26 IndexedDBTransaction* transaction)
26 : task_type_(task_type), 27 : task_type_(task_type),
27 cursor_type_(cursor_type), 28 cursor_type_(cursor_type),
28 transaction_(transaction), 29 transaction_(transaction),
29 cursor_(std::move(cursor)), 30 cursor_(std::move(cursor)),
30 closed_(false) { 31 closed_(false) {
31 transaction_->RegisterOpenCursor(this); 32 transaction_->RegisterOpenCursor(this);
32 } 33 }
33 34
34 IndexedDBCursor::~IndexedDBCursor() { 35 IndexedDBCursor::~IndexedDBCursor() {
35 transaction_->UnregisterOpenCursor(this); 36 transaction_->UnregisterOpenCursor(this);
36 } 37 }
37 38
38 void IndexedDBCursor::Continue(std::unique_ptr<IndexedDBKey> key, 39 void IndexedDBCursor::Continue(std::unique_ptr<IndexedDBKey> key,
39 std::unique_ptr<IndexedDBKey> primary_key, 40 std::unique_ptr<IndexedDBKey> primary_key,
40 scoped_refptr<IndexedDBCallbacks> callbacks) { 41 scoped_refptr<IndexedDBCallbacks> callbacks) {
41 IDB_TRACE("IndexedDBCursor::Continue"); 42 IDB_TRACE("IndexedDBCursor::Continue");
42 43
44 if (closed_) {
cmumford 2016/11/21 18:29:22 No problem with your check, but Do you think we ne
dmurph 2016/11/22 23:33:10 Done.
45 callbacks->OnError(
46 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
47 "The cursor has been closed."));
48 return;
49 }
50
43 transaction_->ScheduleTask( 51 transaction_->ScheduleTask(
44 task_type_, 52 task_type_,
45 base::Bind(&IndexedDBCursor::CursorIterationOperation, 53 base::Bind(&IndexedDBCursor::CursorIterationOperation,
46 this, 54 this,
47 base::Passed(&key), 55 base::Passed(&key),
48 base::Passed(&primary_key), 56 base::Passed(&primary_key),
49 callbacks)); 57 callbacks));
50 } 58 }
51 59
52 void IndexedDBCursor::Advance(uint32_t count, 60 void IndexedDBCursor::Advance(uint32_t count,
53 scoped_refptr<IndexedDBCallbacks> callbacks) { 61 scoped_refptr<IndexedDBCallbacks> callbacks) {
54 IDB_TRACE("IndexedDBCursor::Advance"); 62 IDB_TRACE("IndexedDBCursor::Advance");
55 63
64 if (closed_) {
65 callbacks->OnError(
66 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
67 "The cursor has been closed."));
68 return;
69 }
70
56 transaction_->ScheduleTask( 71 transaction_->ScheduleTask(
57 task_type_, 72 task_type_,
58 base::Bind( 73 base::Bind(
59 &IndexedDBCursor::CursorAdvanceOperation, this, count, callbacks)); 74 &IndexedDBCursor::CursorAdvanceOperation, this, count, callbacks));
60 } 75 }
61 76
62 void IndexedDBCursor::CursorAdvanceOperation( 77 IndexedDBTransaction::OperationResult IndexedDBCursor::CursorAdvanceOperation(
63 uint32_t count, 78 uint32_t count,
64 scoped_refptr<IndexedDBCallbacks> callbacks, 79 scoped_refptr<IndexedDBCallbacks> callbacks,
65 IndexedDBTransaction* /*transaction*/) { 80 IndexedDBTransaction* /*transaction*/) {
81 DCHECK(cursor_);
66 IDB_TRACE("IndexedDBCursor::CursorAdvanceOperation"); 82 IDB_TRACE("IndexedDBCursor::CursorAdvanceOperation");
67 leveldb::Status s; 83 leveldb::Status s = leveldb::Status::OK();
68 // TODO(cmumford): Handle this error (crbug.com/363397). Although this will 84
69 // properly fail, caller will not know why, and any corruption 85 if (cursor_->Advance(count, &s)) {
70 // will be ignored. 86 callbacks->OnSuccess(key(), primary_key(), Value());
71 if (!cursor_ || !cursor_->Advance(count, &s)) { 87 return s;
72 cursor_.reset();
73 callbacks->OnSuccess(nullptr);
74 return;
75 } 88 }
76 89
77 callbacks->OnSuccess(key(), primary_key(), Value()); 90 Close();
91 callbacks->OnError(IndexedDBDatabaseError(
92 blink::WebIDBDatabaseExceptionUnknownError, "Error advancing cursor"));
93
94 return s;
78 } 95 }
79 96
80 void IndexedDBCursor::CursorIterationOperation( 97 IndexedDBTransaction::OperationResult IndexedDBCursor::CursorIterationOperation(
81 std::unique_ptr<IndexedDBKey> key, 98 std::unique_ptr<IndexedDBKey> key,
82 std::unique_ptr<IndexedDBKey> primary_key, 99 std::unique_ptr<IndexedDBKey> primary_key,
83 scoped_refptr<IndexedDBCallbacks> callbacks, 100 scoped_refptr<IndexedDBCallbacks> callbacks,
84 IndexedDBTransaction* /*transaction*/) { 101 IndexedDBTransaction* /*transaction*/) {
102 DCHECK(cursor_);
85 IDB_TRACE("IndexedDBCursor::CursorIterationOperation"); 103 IDB_TRACE("IndexedDBCursor::CursorIterationOperation");
86 leveldb::Status s; 104 leveldb::Status s = leveldb::Status::OK();
87 // TODO(cmumford): Handle this error (crbug.com/363397). Although this will 105
88 // properly fail, caller will not know why, and any corruption 106 if (!cursor_->Continue(key.get(), primary_key.get(),
89 // will be ignored. 107 IndexedDBBackingStore::Cursor::SEEK, &s)) {
90 if (!cursor_ || !cursor_->Continue(key.get(), 108 if (!s.ok()) {
91 primary_key.get(), 109 Close();
92 IndexedDBBackingStore::Cursor::SEEK, 110 callbacks->OnError(
93 &s) || !s.ok()) { 111 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
94 cursor_.reset(); 112 "Error advancing cursor"));
cmumford 2016/11/21 18:29:22 Tweak error message - same as AdvanceOperation abo
dmurph 2016/11/22 23:33:10 Done.
95 callbacks->OnSuccess(nullptr); 113 } else {
96 return; 114 // This happens if we reach the end of the iterator and can't continue.
115 // Current behavior (if it ever gets hit) is to return a null.
116 callbacks->OnSuccess(nullptr);
117 }
118 return s;
97 } 119 }
98 120
99 callbacks->OnSuccess(this->key(), this->primary_key(), Value()); 121 callbacks->OnSuccess(this->key(), this->primary_key(), Value());
122 return s;
100 } 123 }
101 124
102 void IndexedDBCursor::PrefetchContinue( 125 void IndexedDBCursor::PrefetchContinue(
103 int number_to_fetch, 126 int number_to_fetch,
104 scoped_refptr<IndexedDBCallbacks> callbacks) { 127 scoped_refptr<IndexedDBCallbacks> callbacks) {
128 DCHECK(cursor_);
105 IDB_TRACE("IndexedDBCursor::PrefetchContinue"); 129 IDB_TRACE("IndexedDBCursor::PrefetchContinue");
106 130
131 if (closed_) {
132 callbacks->OnError(
133 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
134 "The cursor has been closed."));
135 return;
136 }
137
107 transaction_->ScheduleTask( 138 transaction_->ScheduleTask(
108 task_type_, 139 task_type_,
109 base::Bind(&IndexedDBCursor::CursorPrefetchIterationOperation, 140 base::Bind(&IndexedDBCursor::CursorPrefetchIterationOperation,
110 this, 141 this,
111 number_to_fetch, 142 number_to_fetch,
112 callbacks)); 143 callbacks));
113 } 144 }
114 145
115 void IndexedDBCursor::CursorPrefetchIterationOperation( 146 IndexedDBTransaction::OperationResult
147 IndexedDBCursor::CursorPrefetchIterationOperation(
116 int number_to_fetch, 148 int number_to_fetch,
117 scoped_refptr<IndexedDBCallbacks> callbacks, 149 scoped_refptr<IndexedDBCallbacks> callbacks,
118 IndexedDBTransaction* /*transaction*/) { 150 IndexedDBTransaction* /*transaction*/) {
119 IDB_TRACE("IndexedDBCursor::CursorPrefetchIterationOperation"); 151 IDB_TRACE("IndexedDBCursor::CursorPrefetchIterationOperation");
152 leveldb::Status s = leveldb::Status::OK();
120 153
121 std::vector<IndexedDBKey> found_keys; 154 std::vector<IndexedDBKey> found_keys;
122 std::vector<IndexedDBKey> found_primary_keys; 155 std::vector<IndexedDBKey> found_primary_keys;
123 std::vector<IndexedDBValue> found_values; 156 std::vector<IndexedDBValue> found_values;
124 157
125 saved_cursor_.reset(); 158 saved_cursor_.reset();
126 // TODO(cmumford): Use IPC::Channel::kMaximumMessageSize 159 // TODO(cmumford): Use IPC::Channel::kMaximumMessageSize
127 const size_t max_size_estimate = 10 * 1024 * 1024; 160 const size_t max_size_estimate = 10 * 1024 * 1024;
128 size_t size_estimate = 0; 161 size_t size_estimate = 0;
129 leveldb::Status s;
130 162
131 // TODO(cmumford): Handle this error (crbug.com/363397). Although this will 163 // TODO(cmumford): Handle this error (crbug.com/363397). Although this will
132 // properly fail, caller will not know why, and any corruption 164 // properly fail, caller will not know why, and any corruption
133 // will be ignored. 165 // will be ignored.
134 for (int i = 0; i < number_to_fetch; ++i) { 166 for (int i = 0; i < number_to_fetch; ++i) {
135 if (!cursor_ || !cursor_->Continue(&s)) { 167 if (!cursor_->Continue(&s)) {
136 cursor_.reset(); 168 if (s.ok()) {
137 break; 169 // We've reached the end, so just return what we have.
170 break;
171 }
172 Close();
173 callbacks->OnError(
174 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
175 "Error advancing cursor"));
176 return s;
138 } 177 }
139 178
140 if (i == 0) { 179 if (i == 0) {
141 // First prefetched result is always used, so that's the position 180 // First prefetched result is always used, so that's the position
142 // a cursor should be reset to if the prefetch is invalidated. 181 // a cursor should be reset to if the prefetch is invalidated.
143 saved_cursor_ = cursor_->Clone(); 182 saved_cursor_ = cursor_->Clone();
144 } 183 }
145 184
146 found_keys.push_back(cursor_->key()); 185 found_keys.push_back(cursor_->key());
147 found_primary_keys.push_back(cursor_->primary_key()); 186 found_primary_keys.push_back(cursor_->primary_key());
(...skipping 14 matching lines...) Expand all
162 } 201 }
163 size_estimate += cursor_->key().size_estimate(); 202 size_estimate += cursor_->key().size_estimate();
164 size_estimate += cursor_->primary_key().size_estimate(); 203 size_estimate += cursor_->primary_key().size_estimate();
165 204
166 if (size_estimate > max_size_estimate) 205 if (size_estimate > max_size_estimate)
167 break; 206 break;
168 } 207 }
169 208
170 if (found_keys.empty()) { 209 if (found_keys.empty()) {
171 callbacks->OnSuccess(nullptr); 210 callbacks->OnSuccess(nullptr);
172 return; 211 return s;
173 } 212 }
174 213
175 callbacks->OnSuccessWithPrefetch( 214 callbacks->OnSuccessWithPrefetch(
176 found_keys, found_primary_keys, &found_values); 215 found_keys, found_primary_keys, &found_values);
216 return s;
177 } 217 }
178 218
179 leveldb::Status IndexedDBCursor::PrefetchReset(int used_prefetches, 219 leveldb::Status IndexedDBCursor::PrefetchReset(int used_prefetches,
180 int /* unused_prefetches */) { 220 int /* unused_prefetches */) {
181 IDB_TRACE("IndexedDBCursor::PrefetchReset"); 221 IDB_TRACE("IndexedDBCursor::PrefetchReset");
182 cursor_.swap(saved_cursor_); 222 cursor_.swap(saved_cursor_);
183 saved_cursor_.reset(); 223 saved_cursor_.reset();
184 leveldb::Status s; 224 leveldb::Status s;
185 225
186 if (closed_) 226 if (closed_)
(...skipping 11 matching lines...) Expand all
198 } 238 }
199 239
200 void IndexedDBCursor::Close() { 240 void IndexedDBCursor::Close() {
201 IDB_TRACE("IndexedDBCursor::Close"); 241 IDB_TRACE("IndexedDBCursor::Close");
202 closed_ = true; 242 closed_ = true;
203 cursor_.reset(); 243 cursor_.reset();
204 saved_cursor_.reset(); 244 saved_cursor_.reset();
205 } 245 }
206 246
207 } // namespace content 247 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698