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

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

Issue 2506773002: [IndexedDB] Integrating failures and corruption with transaction (Closed)
Patch Set: removed extra log statements Created 4 years 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_) {
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 leveldb::Status 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*/) {
66 IDB_TRACE("IndexedDBCursor::CursorAdvanceOperation"); 81 IDB_TRACE("IndexedDBCursor::CursorAdvanceOperation");
67 leveldb::Status s; 82 leveldb::Status s = leveldb::Status::OK();
68 // TODO(cmumford): Handle this error (crbug.com/363397). Although this will 83
69 // properly fail, caller will not know why, and any corruption
70 // will be ignored.
71 if (!cursor_ || !cursor_->Advance(count, &s)) { 84 if (!cursor_ || !cursor_->Advance(count, &s)) {
72 cursor_.reset(); 85 cursor_.reset();
73 callbacks->OnSuccess(nullptr); 86 if (s.ok()) {
74 return; 87 callbacks->OnSuccess(nullptr);
88 return s;
89 }
90 Close();
91 callbacks->OnError(IndexedDBDatabaseError(
92 blink::WebIDBDatabaseExceptionUnknownError, "Error advancing cursor"));
93 return s;
75 } 94 }
76 95
77 callbacks->OnSuccess(key(), primary_key(), Value()); 96 callbacks->OnSuccess(key(), primary_key(), Value());
97 return s;
78 } 98 }
79 99
80 void IndexedDBCursor::CursorIterationOperation( 100 leveldb::Status IndexedDBCursor::CursorIterationOperation(
81 std::unique_ptr<IndexedDBKey> key, 101 std::unique_ptr<IndexedDBKey> key,
82 std::unique_ptr<IndexedDBKey> primary_key, 102 std::unique_ptr<IndexedDBKey> primary_key,
83 scoped_refptr<IndexedDBCallbacks> callbacks, 103 scoped_refptr<IndexedDBCallbacks> callbacks,
84 IndexedDBTransaction* /*transaction*/) { 104 IndexedDBTransaction* /*transaction*/) {
85 IDB_TRACE("IndexedDBCursor::CursorIterationOperation"); 105 IDB_TRACE("IndexedDBCursor::CursorIterationOperation");
86 leveldb::Status s; 106 leveldb::Status s = leveldb::Status::OK();
87 // TODO(cmumford): Handle this error (crbug.com/363397). Although this will 107
88 // properly fail, caller will not know why, and any corruption 108 if (!cursor_ ||
89 // will be ignored. 109 !cursor_->Continue(key.get(), primary_key.get(),
90 if (!cursor_ || !cursor_->Continue(key.get(), 110 IndexedDBBackingStore::Cursor::SEEK, &s)) {
91 primary_key.get(),
92 IndexedDBBackingStore::Cursor::SEEK,
93 &s) || !s.ok()) {
94 cursor_.reset(); 111 cursor_.reset();
95 callbacks->OnSuccess(nullptr); 112 if (s.ok()) {
96 return; 113 // This happens if we reach the end of the iterator and can't continue.
114 callbacks->OnSuccess(nullptr);
115 return s;
116 }
117 Close();
118 callbacks->OnError(
119 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
120 "Error continuing cursor."));
121 return s;
97 } 122 }
98 123
99 callbacks->OnSuccess(this->key(), this->primary_key(), Value()); 124 callbacks->OnSuccess(this->key(), this->primary_key(), Value());
125 return s;
100 } 126 }
101 127
102 void IndexedDBCursor::PrefetchContinue( 128 void IndexedDBCursor::PrefetchContinue(
103 int number_to_fetch, 129 int number_to_fetch,
104 scoped_refptr<IndexedDBCallbacks> callbacks) { 130 scoped_refptr<IndexedDBCallbacks> callbacks) {
105 IDB_TRACE("IndexedDBCursor::PrefetchContinue"); 131 IDB_TRACE("IndexedDBCursor::PrefetchContinue");
106 132
133 if (closed_) {
134 callbacks->OnError(
135 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
136 "The cursor has been closed."));
137 return;
138 }
139
107 transaction_->ScheduleTask( 140 transaction_->ScheduleTask(
108 task_type_, 141 task_type_,
109 base::Bind(&IndexedDBCursor::CursorPrefetchIterationOperation, 142 base::Bind(&IndexedDBCursor::CursorPrefetchIterationOperation,
110 this, 143 this,
111 number_to_fetch, 144 number_to_fetch,
112 callbacks)); 145 callbacks));
113 } 146 }
114 147
115 void IndexedDBCursor::CursorPrefetchIterationOperation( 148 leveldb::Status IndexedDBCursor::CursorPrefetchIterationOperation(
116 int number_to_fetch, 149 int number_to_fetch,
117 scoped_refptr<IndexedDBCallbacks> callbacks, 150 scoped_refptr<IndexedDBCallbacks> callbacks,
118 IndexedDBTransaction* /*transaction*/) { 151 IndexedDBTransaction* /*transaction*/) {
119 IDB_TRACE("IndexedDBCursor::CursorPrefetchIterationOperation"); 152 IDB_TRACE("IndexedDBCursor::CursorPrefetchIterationOperation");
153 leveldb::Status s = leveldb::Status::OK();
120 154
121 std::vector<IndexedDBKey> found_keys; 155 std::vector<IndexedDBKey> found_keys;
122 std::vector<IndexedDBKey> found_primary_keys; 156 std::vector<IndexedDBKey> found_primary_keys;
123 std::vector<IndexedDBValue> found_values; 157 std::vector<IndexedDBValue> found_values;
124 158
125 saved_cursor_.reset(); 159 saved_cursor_.reset();
126 // TODO(cmumford): Use IPC::Channel::kMaximumMessageSize 160 // TODO(cmumford): Use IPC::Channel::kMaximumMessageSize
127 const size_t max_size_estimate = 10 * 1024 * 1024; 161 const size_t max_size_estimate = 10 * 1024 * 1024;
128 size_t size_estimate = 0; 162 size_t size_estimate = 0;
129 leveldb::Status s;
130 163
131 // TODO(cmumford): Handle this error (crbug.com/363397). Although this will 164 // TODO(cmumford): Handle this error (crbug.com/363397). Although this will
132 // properly fail, caller will not know why, and any corruption 165 // properly fail, caller will not know why, and any corruption
133 // will be ignored. 166 // will be ignored.
134 for (int i = 0; i < number_to_fetch; ++i) { 167 for (int i = 0; i < number_to_fetch; ++i) {
135 if (!cursor_ || !cursor_->Continue(&s)) { 168 if (!cursor_ || !cursor_->Continue(&s)) {
136 cursor_.reset(); 169 cursor_.reset();
137 break; 170 if (s.ok()) {
171 // We've reached the end, so just return what we have.
172 break;
173 }
174 Close();
175 callbacks->OnError(
176 IndexedDBDatabaseError(blink::WebIDBDatabaseExceptionUnknownError,
177 "Error continuing cursor."));
178 return s;
138 } 179 }
139 180
140 if (i == 0) { 181 if (i == 0) {
141 // First prefetched result is always used, so that's the position 182 // First prefetched result is always used, so that's the position
142 // a cursor should be reset to if the prefetch is invalidated. 183 // a cursor should be reset to if the prefetch is invalidated.
143 saved_cursor_ = cursor_->Clone(); 184 saved_cursor_ = cursor_->Clone();
144 } 185 }
145 186
146 found_keys.push_back(cursor_->key()); 187 found_keys.push_back(cursor_->key());
147 found_primary_keys.push_back(cursor_->primary_key()); 188 found_primary_keys.push_back(cursor_->primary_key());
(...skipping 14 matching lines...) Expand all
162 } 203 }
163 size_estimate += cursor_->key().size_estimate(); 204 size_estimate += cursor_->key().size_estimate();
164 size_estimate += cursor_->primary_key().size_estimate(); 205 size_estimate += cursor_->primary_key().size_estimate();
165 206
166 if (size_estimate > max_size_estimate) 207 if (size_estimate > max_size_estimate)
167 break; 208 break;
168 } 209 }
169 210
170 if (found_keys.empty()) { 211 if (found_keys.empty()) {
171 callbacks->OnSuccess(nullptr); 212 callbacks->OnSuccess(nullptr);
172 return; 213 return s;
173 } 214 }
174 215
175 callbacks->OnSuccessWithPrefetch( 216 callbacks->OnSuccessWithPrefetch(
176 found_keys, found_primary_keys, &found_values); 217 found_keys, found_primary_keys, &found_values);
218 return s;
177 } 219 }
178 220
179 leveldb::Status IndexedDBCursor::PrefetchReset(int used_prefetches, 221 leveldb::Status IndexedDBCursor::PrefetchReset(int used_prefetches,
180 int /* unused_prefetches */) { 222 int /* unused_prefetches */) {
181 IDB_TRACE("IndexedDBCursor::PrefetchReset"); 223 IDB_TRACE("IndexedDBCursor::PrefetchReset");
182 cursor_.swap(saved_cursor_); 224 cursor_.swap(saved_cursor_);
183 saved_cursor_.reset(); 225 saved_cursor_.reset();
184 leveldb::Status s; 226 leveldb::Status s;
185 227
186 if (closed_) 228 if (closed_)
187 return s; 229 return s;
188 if (cursor_) { 230 // First prefetched result is always used.
189 // First prefetched result is always used. 231 if (cursor_){
190 DCHECK_GT(used_prefetches, 0); 232 DCHECK_GT(used_prefetches, 0);
191 for (int i = 0; i < used_prefetches - 1; ++i) { 233 for (int i = 0; i < used_prefetches - 1; ++i) {
192 bool ok = cursor_->Continue(&s); 234 bool ok = cursor_->Continue(&s);
193 DCHECK(ok); 235 DCHECK(ok);
194 } 236 }
195 } 237 }
196 238
197 return s; 239 return s;
198 } 240 }
199 241
200 void IndexedDBCursor::Close() { 242 void IndexedDBCursor::Close() {
201 IDB_TRACE("IndexedDBCursor::Close"); 243 IDB_TRACE("IndexedDBCursor::Close");
202 closed_ = true; 244 closed_ = true;
203 cursor_.reset(); 245 cursor_.reset();
204 saved_cursor_.reset(); 246 saved_cursor_.reset();
205 } 247 }
206 248
207 } // namespace content 249 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/indexed_db/indexed_db_cursor.h ('k') | content/browser/indexed_db/indexed_db_database.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698